commit 15044435fb627392d1b361e10ae9b2d54d76dec6 Author: PProvost Date: Mon May 11 09:03:23 2020 -0600 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..cbdd44a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,41 @@ +.git* export-ignore +.hooks* export-ignore + +# Custom attribute to mark sources as using our C code style. +[attr]our-c-style whitespace=tab-in-indent eol=lf format.clang-format-6.0 + +# Custom attribute to mark sources as generated. +# Do not perform whitespace checks. Do not format. +[attr]generated whitespace=-tab-in-indent,-indent-with-non-tab -format.clang-format-6.0 + +bootstrap eol=lf +configure eol=lf +*.[1-9] eol=lf +*.bash eol=lf +*.sh eol=lf +*.sh.in eol=lf + +*.bat eol=crlf +*.bat.in eol=crlf +*.sln eol=crlf +*.vcproj eol=crlf +*.inf eol=crlf + +*.pfx -text +*.png -text +*.png.in -text + +*.c our-c-style +*.cc our-c-style +*.cpp our-c-style +*.cu our-c-style +*.cxx our-c-style +*.h our-c-style +*.hh our-c-style +*.hpp our-c-style +*.hxx our-c-style +*.notcu our-c-style + +*.cmake whitespace=tab-in-indent +*.rst whitespace=tab-in-indent conflict-marker-size=79 +*.txt whitespace=tab-in-indent diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..9c33dc7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +.vscode/ +_deps/ +build/ +CMakeFiles/ +CMakeScripts/ +CMakeLists.txt.user +CMakeCache.txt +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..3a6d0e5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,51 @@ +cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR) + +# Set up the project +project(usbx + VERSION 6.0.0 + LANGUAGES C ASM +) + +if(NOT DEFINED THREADX_ARCH) + message(FATAL_ERROR "Error: THREADX_ARCH not defined") +endif() +if(NOT DEFINED THREADX_TOOLCHAIN) + message(FATAL_ERROR "Error: THREADX_TOOLCHAIN not defined") +endif() + +# Define our target library and an alias for consumers +add_library(${PROJECT_NAME}) +add_library("azrtos::${PROJECT_NAME}" ALIAS ${PROJECT_NAME}) + +# Define any required dependencies between this library and others +target_link_libraries(${PROJECT_NAME} PUBLIC + "azrtos::threadx" + "azrtos::filex" + "azrtos::netxduo" +) + +# A place for generated/copied include files +set(CUSTOM_INC_DIR ${CMAKE_CURRENT_BINARY_DIR}/custom_inc) + +# Pick up the port specific stuff first +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}) + +# Then the common files +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/common) + + + + +# If the user provided an override, copy it to the custom directory +if (NOT UX_USER_FILE) + message(STATUS "Using default ux_user.h file") + set(UX_USER_FILE ${CMAKE_CURRENT_LIST_DIR}/common/inc/ux_user_sample.h) +else() + message(STATUS "Using custom ux_user.h file from ${UX_USER_FILE}") +endif() +configure_file(${UX_USER_FILE} ${CUSTOM_INC_DIR}/ux_user.h COPYONLY) +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CUSTOM_INC_DIR} +) +target_compile_definitions(${PROJECT_NAME} PUBLIC "UX_INCLUDE_USER_DEFINE_FILE" ) diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..76974a3 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,246 @@ +MICROSOFT SOFTWARE LICENSE TERMS + +MICROSOFT AZURE RTOS + +Shape + +These license terms are an agreement between you and Microsoft Corporation (or +one of its affiliates). They apply to the software named above and any Microsoft +services or software updates (except to the extent such services or updates are +accompanied by new or additional terms, in which case those different terms +apply prospectively and do not alter your or Microsoft’s rights relating to +pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU +HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. + +INSTALLATION AND USE RIGHTS. + +General. You may install and use the software and the included Microsoft +applications solely for internal development, testing and evaluation purposes. +Any distribution or production use requires a separate license as set forth in +Section 2. + +Contributions. Microsoft welcomes contributions to this software. In the event +that you make a contribution to this software you will be required to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and +actually do, grant Microsoft the rights to use your contribution. For details, +visit https://cla.microsoft.com. + +Included Microsoft Applications. The software includes other Microsoft +applications which are governed by the licenses embedded in or made available +with those applications. + +Third Party Components. The software may include third party components with +separate legal notices or governed by other agreements, as may be described +within the software or in the ThirdPartyNotices file(s) accompanying the +software. + +Competitive Benchmarking. If you are a direct competitor, and you access or use +the software for purposes of competitive benchmarking, analysis, or intelligence +gathering, you waive as against Microsoft, its subsidiaries, and its affiliated +companies (including prospectively) any competitive use, access, and +benchmarking test restrictions in the terms governing your software to the +extent your terms of use are, or purport to be, more restrictive than +Microsoft’s terms. If you do not waive any such purported restrictions in the +terms governing your software, you are not allowed to access or use this +software, and will not do so. + +DISTRIBUTION AND PRODUCTION USE. If you have obtained and/or are developing on +microprocessor(s) and/or microcontroller(s) (“hardware”) listed in the file +named “LICENSED-HARDWARE.txt” included in the repository and/or distributed with +the software you have the following rights in and to the software solely when +used in combination with the hardware. In the event hardware is not listed in +the LICENSED-HARDWARE.txt file, you do not have the rights in this Section 2. + +Distribution and Production Use Rights. + +You may use the software in production (e.g. program the modified or unmodified +software to devices you own or control) and distribute (i.e. make available to +third parties) the modified or unmodified binary image produced from this code. + + +You may permit your device distributors or developers to copy and distribute the +binary image as programmed or to be programmed to your devices. + +You may redistribute the unmodified or modified source to your device +distributors or developers. Modifications must be clearly marked. Any +redistribution in source code form must contain this license and any other +licenses that accompany the software. + +Requirements. For any code you distribute, you must: + +when distributed in binary form, except as embedded in a device, include with +such distribution the terms of this agreement; + +when distributed in source code form to distributors or developers of your +devices, include with such distribution the terms of this agreement; and + +indemnify, defend and hold harmless Microsoft from any claims, including +attorneys’ fees, related to the distribution or use of your devices, except to +the extent that any claim is based solely on the unmodified software. + +Restrictions. You may not: + +use or modify the software to create a competing real time operating system +software; + +remove any copyright notices or licenses contained in the software; + +use Microsoft’s trademarks or trade dress in your application in any way that +suggests your device or application comes from or is endorsed by Microsoft; + +transfer individual components, specific libraries, classes, functions or code +fragments of the software separately for purposes unrelated to the software; or + +use or distribute the software in any way that would subject the software or +Microsoft’s intellectual property or technology to any other license terms. + +SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all +other rights. Unless applicable law gives you more rights despite this +limitation, you will not (and have no right to): + +remove, minimize, block, or modify any notices of Microsoft or its suppliers in +the software; + +use the software in any way that is against the law or to create or propagate +malware; or + +share, publish, distribute, or lease the software (except as permitted in +Section 2 above), or provide the software as a stand-alone offering for others +to use. + +DATA. This software may interact with other Microsoft products that collect data +that is transmitted to Microsoft. To learn more about how Microsoft processes +personal data we collect, please see the Microsoft Privacy Statement at +https://go.microsoft.com/fwlink/?LinkId=248681. + +EXPORT RESTRICTIONS. You must comply with all domestic and international export +laws and regulations that apply to the software, which include restrictions on +destinations, end users, and end use. For further information on export +restrictions, visit https://aka.ms/exporting. + +SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any +support services for the software. Any support provided is “as is”, “with all +faults”, and without warranty of any kind. + +UPDATES. Microsoft may periodically update the software. You may obtain updates +only from Microsoft or Microsoft-authorized sources. Updates may not include or +support all existing software features, services, or peripheral devices. + +TERMINATION. Without prejudice to any other rights, Microsoft may terminate this +agreement if you fail to comply with any of its terms or conditions. In such +event, you must destroy all copies of the software and all of its component +parts. + +ENTIRE AGREEMENT. This agreement, and any other terms Microsoft may provide for +supplements, updates, or third-party applications, is the entire agreement for +the software. To the extent you have entered into a separate agreement with +Microsoft relating specifically to the software, the terms in such agreement +shall control. + +APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in +the United States or Canada, the laws of the state or province where you live +(or, if a business, where your principal place of business is located) govern +the interpretation of this agreement, claims for its breach, and all other +claims (including consumer protection, unfair competition, and tort claims), +regardless of conflict of laws principles. If you acquired the software in any +other country, its laws apply. If U.S. federal jurisdiction exists, you and +Microsoft consent to exclusive jurisdiction and venue in the federal court in +King County, Washington for all disputes heard in court. If not, you and +Microsoft consent to exclusive jurisdiction and venue in the Superior Court of +King County, Washington for all disputes heard in court. + +CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal +rights. You may have other rights, including consumer rights, under the laws of +your state or country. Separate and apart from your relationship with Microsoft, +you may also have rights with respect to the party from which you acquired the +software. This agreement does not change those other rights if the laws of your +state or country do not permit it to do so. For example, if you acquired the +software in one of the below regions, or mandatory country law applies, then the +following provisions apply to you: + +Australia. You have statutory guarantees under the Australian Consumer Law and +nothing in this agreement is intended to affect those rights. + +Germany and Austria. + +i.Warranty. The properly licensed software will perform substantially as +described in any Microsoft materials that accompany the software. However, +Microsoft gives no contractual guarantee in relation to the licensed software. + +ii.Limitation of Liability. In case of intentional conduct, gross negligence, +claims based on the Product Liability Act, as well as, in case of death or +personal or physical injury, Microsoft is liable according to the statutory law. + + +Subject to the foregoing clause ii., Microsoft will only be liable for slight +negligence if Microsoft is in breach of such material contractual obligations, +the fulfillment of which facilitate the due performance of this agreement, the +breach of which would endanger the purpose of this agreement and the compliance +with which a party may constantly trust in (so-called "cardinal obligations"). +In other cases of slight negligence, Microsoft will not be liable for slight +negligence. + +DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF +USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO +THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED +WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND +NON-INFRINGEMENT. + +LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING +DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM +MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT +RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, +INDIRECT, OR INCIDENTAL DAMAGES. + +This limitation applies to (a) anything related to the software, services, +content (including code) on third party Internet sites, or third party +applications; and (b) claims for breach of contract, warranty, guarantee, or +condition; strict liability, negligence, or other tort; or any other claim; in +each case to the extent permitted by applicable law. + +It also applies even if Microsoft knew or should have known about the +possibility of the damages. The above limitation or exclusion may not apply to +you because your state, province, or country may not allow the exclusion or +limitation of incidental, consequential, or other damages. + + + +Please note: As this software is distributed in Canada, some of the clauses in +this agreement are provided below in French. + +Remarque: Ce logiciel étant distribué au Canada, certaines des clauses dans ce +contrat sont fournies ci-dessous en français. + +EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « tel quel +». Toute utilisation de ce logiciel est à votre seule risque et péril. Microsoft +n’accorde aucune autre garantie expresse. Vous pouvez bénéficier de droits +additionnels en vertu du droit local sur la protection des consommateurs, que ce +contrat ne peut modifier. La ou elles sont permises par le droit locale, les +garanties implicites de qualité marchande, d’adéquation à un usage particulier +et d’absence de contrefaçon sont exclues. + +LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES +DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une +indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ US. Vous +ne pouvez prétendre à aucune indemnisation pour les autres dommages, y compris +les dommages spéciaux, indirects ou accessoires et pertes de bénéfices. + +Cette limitation concerne: + +•tout ce qui est relié au logiciel, aux services ou au contenu (y compris le +code) figurant sur des sites Internet tiers ou dans des programmes tiers; et + +•les réclamations au titre de violation de contrat ou de garantie, ou au titre +de responsabilité stricte, de négligence ou d’une autre faute dans la limite +autorisée par la loi en vigueur. + +Elle s’applique également, même si Microsoft connaissait ou devrait connaître +l’éventualité d’un tel dommage. Si votre pays n’autorise pas l’exclusion ou la +limitation de responsabilité pour les dommages indirects, accessoires ou de +quelque nature que ce soit, il se peut que la limitation ou l’exclusion +ci-dessus ne s’appliquera pas à votre égard. + +EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. Vous +pourriez avoir d’autres droits prévus par les lois de votre pays. Le présent +contrat ne modifie pas les droits que vous confèrent les lois de votre pays si +celles-ci ne le permettent pas. \ No newline at end of file diff --git a/LICENSED-HARDWARE.txt b/LICENSED-HARDWARE.txt new file mode 100644 index 0000000..77dd1ab --- /dev/null +++ b/LICENSED-HARDWARE.txt @@ -0,0 +1,16 @@ +LICENSED HARDWARE LIST + +Last Updated: 2020-05-08 + +Microsoft has entered into OEM Agreements with manufacturers of the following +microprocessors and microcontrollers (the “hardware”) to enable those +manufacturers to include and distribute Azure RTOS in certain hardware. If you +have obtained and/or are developing on microprocessor(s) and/or +microcontroller(s) (“hardware”) listed below you inherit the “Distribution and +Production Use” rights in Section 2 of the Microsoft Software License Terms for +Microsoft Azure RTOS. If hardware is not listed below, you do not have those +rights. + +-------------------------------------------------------------------------------- + +More coming soon. Please check back frequently for updates. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100755 index 0000000..379da1b --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# USBX \ No newline at end of file diff --git a/TODO b/TODO new file mode 100644 index 0000000..e69de29 diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt new file mode 100644 index 0000000..4b30487 --- /dev/null +++ b/common/CMakeLists.txt @@ -0,0 +1,1804 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_api.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_altera.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_at91.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_at91hs.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_atm7.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_bf52.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_isp1181.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_kxxf.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_lpc3131.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_lpc3180.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_mcf5329.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_mcimx6.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_ml6965.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_musb.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_pic32.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_ppc440.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_rx.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_rz.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_sh2a.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_sh7705.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_sim_slave.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_spear.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_stm32.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_ti18x.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_dcd_tilm3.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_class_audio.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_class_audio10.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_class_audio20.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_class_cdc_acm.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_class_cdc_ecm.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_class_dfu.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_class_dpump.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_class_hid.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_class_pima.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_class_rndis.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_class_storage.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_device_stack.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_atm7.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_ehci.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_isp1161.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_isp1362.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_kxxf.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_musb.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_ohci.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_pic32.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_rx.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_rz.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_sh2a.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_sim_host.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_hcd_stm32.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_asix.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_audio.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_cdc_acm.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_cdc_ecm.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_dpump.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_gser.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_hid.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_hid_keyboard.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_hid_mouse.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_hid_remote_control.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_hub.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_pima.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_printer.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_prolific.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_storage.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_swar.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_class_video.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_host_stack.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_network_driver.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_system.h + ${CMAKE_CURRENT_LIST_DIR}/inc/ux_utility.h + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_delay.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_endpoint_register_address_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_fifo_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_altera_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_at91hs_transfer_request.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_address_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_endpoint_create.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_endpoint_destroy.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_endpoint_reset.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_endpoint_stall.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_endpoint_status.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_fifo_read.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_fifo_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_frame_number_get.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_function.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_initialize.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_initialize_complete.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_interrupt_handler.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_register_clear.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_register_read.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_register_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_register_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_state_change.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_transfer_callback.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_atm7_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_endpoint_register_address_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_bf52_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_bandwidth_update.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_command.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_read_data16.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_read_data32.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_write_data16.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_isp1181_write_data32.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_endpoint_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_endpoint_stall_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_get_update_toggle.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_kxxf_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_endpoint_address_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_endpoint_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_endpoint_stall_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_qtd_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_status_phase_hook.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3131_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_command_data_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_command_data_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_command_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_endpoint_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_endpoint_stall_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_lpc3180_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_endpoint_address_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_endpoint_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_endpoint_stall_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_qtd_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_status_phase_hook.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcf5329_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_endpoint_address_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_endpoint_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_endpoint_stall_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_qtd_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_status_phase_hook.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_mcimx6_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ml6965_vbus_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_fifo_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_musb_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_bdt_fill.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_endpoint_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_endpoint_stall_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_pic32_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_endpoint_index_select.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ppc440_vbus_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_buffer_empty_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_buffer_notready_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_buffer_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_buffer_ready_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_buffer_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_current_endpoint_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_data_buffersize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_endpoint_nak_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_fifo_port_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_fifoc_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_fifod_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rx_transfer_request.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_address_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_buffer_empty_interrupt.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_buffer_notready_interrupt.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_buffer_read.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_buffer_ready_interrupt.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_buffer_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_current_endpoint_change.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_data_buffersize.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_dma_register_clear.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_dma_register_read.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_dma_register_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_dma_register_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_dma_rx_interrupt_handler.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_dma_tx_interrupt_handler.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_endpoint_create.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_endpoint_destroy.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_endpoint_nak_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_endpoint_reset.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_endpoint_stall.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_endpoint_status.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_fifo_port_change.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_fifo_read.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_fifoc_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_fifod_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_frame_number_get.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_function.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_initialize.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_initialize_complete.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_interrupt_handler.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_low_level_setup.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_pipe_select.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_register_clear.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_register_read.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_register_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_register_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_state_change.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_transfer_abort.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_transfer_callback.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_rz_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_buffer_empty_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_buffer_notready_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_buffer_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_buffer_ready_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_buffer_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_current_endpoint_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_data_buffer_size.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_endpoint_nak_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_fifo_port_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_fifoc_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_fifod_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh2a_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_endpoint_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sh7705_vbus_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_fifo_address_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_spear_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_delay.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_endpoint_register_address_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_fifo_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_stm32_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_fifo_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_ti18x_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_fifo_flush.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_fifo_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_transfer_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_tilm3_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio10_control_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio20_control_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_frame_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_frame_free.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_frame_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_reception_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read16.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read24.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read32.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read8.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_stream_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_transmission_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_unitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_frame_commit.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_frame_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_bulkin_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_bulkout_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_control_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_unitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_write_with_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_bulkin_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_bulkout_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_uninitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_descriptor_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_event_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_event_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_report_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_report_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_uninitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_control_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_data.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_device_info_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_device_prop_desc_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_device_prop_value_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_device_prop_value_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_device_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_event_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_event_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_data_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_data_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_handles_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_info_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_prop_desc_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_prop_value_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_prop_value_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_props_supported_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_references_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_references_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_objects_number_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_partial_object_data_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_response_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_storage_format.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_storage_id_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_storage_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_bulkin_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_bulkout_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_msg_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_msg_keep_alive.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_msg_query.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_msg_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_msg_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_csw_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_format.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_get_configuration.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_get_performance.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_get_status_notification.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_inquiry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_mode_select.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_mode_sense.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_prevent_allow_media_removal.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read_capacity.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read_disk_information.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read_dvd_structure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read_format_capacity.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read_toc.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_report_key.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_request_sense.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_start_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_synchronize_cache.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_test_ready.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_uninitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_verify.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_alternate_setting_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_alternate_setting_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_class_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_class_unregister.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_clear_feature.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_configuration_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_configuration_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_control_request_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_descriptor_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_disconnect.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_get_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_host_wakeup.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_interface_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_interface_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_interface_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_interface_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_microsoft_extension_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_set_feature.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_transfer_all_request_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_uninitialize.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_asynch_queue_process.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_asynch_schedule.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_asynchronous_endpoint_create.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_asynchronous_endpoint_destroy.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_controller_disable.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_delay.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_ed_obtain.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_ed_td_clean.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_endpoint_reset.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_entry.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_frame_number_get.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_frame_number_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_initialize.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_interrupt_endpoint_create.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_interrupt_handler.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_iso_queue_process.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_iso_schedule.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_isochronous_endpoint_create.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_isochronous_td_obtain.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_periodic_endpoint_destroy.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_periodic_schedule.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_port_disable.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_port_enable.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_port_reset.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_port_resume.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_port_status_get.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_port_suspend.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_power_down_port.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_power_on_port.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_register_clear.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_register_read.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_register_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_register_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_regular_td_obtain.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_request_bulk_transfer.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_request_control_transfer.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_request_interupt_transfer.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_request_isochronous_transfer.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_request_transfer.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_td_schedule.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_atm7_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_asynch_td_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_done_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_door_bell_wait.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_ed_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_fsisochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_hsisochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_interrupt_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_isochronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_next_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_power_root_hubs.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_interrupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_transfer_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_transfer_request_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_asynch_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_asynch_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_atl_buffer_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_atl_buffer_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_ed_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_hcer_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_hcer_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_hcor_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_hcor_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_iso_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_iso_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_periodic_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_periodic_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_port_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_power_root_hubs.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_ptd_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1161_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_aitl_buffer_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_aitl_buffer_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_asynch_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_atl_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_ed_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_hcer_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_hcer_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_hcor_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_hcor_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_interrupt_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_iso_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_iso_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_isochronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_itl_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_periodic_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_port_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_power_root_hubs.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_ptd_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_isp1362_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_asynch_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_asynch_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_delay.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_ed_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_iso_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_iso_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_periodic_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_periodic_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_port_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_td_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_kxxf_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_asynch_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_asynch_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_delay.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_ed_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_iso_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_iso_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_periodic_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_periodic_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_port_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_td_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_musb_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_done_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_endpoint_error_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_next_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_periodic_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_power_root_hubs.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_transfer_request_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_asynch_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_asynch_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_bus_error_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_ed_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_iso_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_iso_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_periodic_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_periodic_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_port_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_td_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_pic32_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_asynch_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_asynch_queue_process_bemp.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_asynch_queue_process_brdy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_asynch_queue_process_nrdy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_asynch_queue_process_sign.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_asynch_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_buffer_empty_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_buffer_notready_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_buffer_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_buffer_ready_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_buffer_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_bulk_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_bulk_int_td_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_control_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_control_td_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_current_endpoint_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_data_buffer_size.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_ed_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_endpoint_nak_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_fifo_port_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_fifoc_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_fifod_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_iso_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_iso_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_periodic_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_periodic_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_port_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_power_root_hubs.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_td_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rx_transfer_abort.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_asynch_queue_process.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_asynch_queue_process_bemp.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_asynch_queue_process_brdy.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_asynch_queue_process_nrdy.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_asynch_queue_process_sign.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_asynch_schedule.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_asynchronous_endpoint_create.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_asynchronous_endpoint_destroy.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_buffer_empty_interrupt.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_buffer_notready_interrupt.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_buffer_read.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_buffer_ready_interrupt.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_buffer_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_bulk_endpoint_create.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_bulk_int_td_add.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_control_endpoint_create.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_control_td_add.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_controller_disable.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_current_endpoint_change.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_data_buffer_size.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_dma_register_clear.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_dma_register_read.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_dma_register_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_dma_register_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_dma_rx_interrupt_handler.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_dma_tx_interrupt_handler.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_ed_obtain.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_ed_td_clean.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_endpoint_nak_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_endpoint_reset.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_entry.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_fifo_port_change.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_fifo_read.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_fifoc_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_fifod_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_frame_number_get.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_frame_number_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_initialize.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_interrupt_endpoint_create.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_interrupt_handler.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_iso_queue_process.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_iso_schedule.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_isochronous_endpoint_create.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_isochronous_td_obtain.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_least_traffic_list_get.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_low_level_setup.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_periodic_endpoint_destroy.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_periodic_schedule.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_periodic_tree_create.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_port_disable.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_port_enable.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_port_reset.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_port_resume.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_port_status_get.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_port_suspend.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_power_down_port.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_power_on_port.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_power_root_hubs.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_register_clear.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_register_read.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_register_set.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_register_write.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_regular_td_obtain.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_request_bulk_transfer.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_request_control_transfer.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_request_interupt_transfer.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_request_isochronous_transfer.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_request_transfer.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_td_add.c + # ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_rz_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_asynch_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_asynch_queue_process_bemp.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_asynch_queue_process_brdy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_asynch_queue_process_nrdy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_asynch_queue_process_sign.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_asynch_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_buffer_empty_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_buffer_notready_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_buffer_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_buffer_ready_interrupt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_buffer_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_bulk_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_bulk_int_td_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_control_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_control_td_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_current_endpoint_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_data_buffer_size.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_ed_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_endpoint_nak_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_fifo_port_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_fifo_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_fifoc_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_fifod_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_iso_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_iso_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_periodic_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_periodic_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_port_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_power_root_hubs.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_td_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sh2a_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_asynch_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_asynch_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_ed_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_iso_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_iso_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_periodic_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_periodic_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_timer_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_transaction_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_asynch_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_asynch_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_channel_halt.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_delay.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_ed_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_initialize_fscore.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_initialize_hscore.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_iso_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_iso_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_periodic_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_periodic_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_port_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_register_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_register_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_td_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_stm32_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_interrupt_notification.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_reception_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_setup.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_transmission_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_alternate_setting_locate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_control_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_control_value_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_control_value_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_descriptor_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_device_controls_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_device_type_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_streaming_sampling_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_streaming_sampling_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_streaming_terminal_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_capabilities_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_command.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_reception_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_reception_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_reception_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_interrupt_notification.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_mac_address_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_reception_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_transmission_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_transmit_queue_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_command.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_reception_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_reception_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_reception_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_client_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_client_search.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_descriptor_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_field_decompress.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_global_item_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_idle_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_idle_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_instance_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_interrupt_endpoint_search.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_item_data_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_key_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_local_item_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_main_item_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_buttons_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_position_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_wheel_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_periodic_report_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_periodic_report_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_remote_control_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_remote_control_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_remote_control_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_remote_control_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_remote_control_usage_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_callback_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_compress.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_decompress.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_descriptor_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_id_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_item_analyse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_resources_free.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_change_detect.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_change_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_descriptor_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_feature.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_hub_change_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_interrupt_endpoint_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_connection_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_enable_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_over_current_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_reset_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_suspend_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_ports_power.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_command.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_device_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_device_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_notification.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_num_objects_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_close.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_copy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_handles_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_info_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_move.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_open.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_request_cancel.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_session_close.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_session_open.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_storage_ids_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_storage_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_thumb_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_name_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_soft_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_command.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_reception_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_reception_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_reception_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_setup.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_cbw_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_device_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_device_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_device_support_check.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_driver_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_max_lun_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_capacity_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_characteristics_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_format_capacity_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_mount.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_open.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_protection_check.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_recovery_sense_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_partition_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_request_sense.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_sense_code_translate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_start_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport_bo.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport_cb.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport_cbi.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_unit_ready_test.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_reception_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_reception_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_reception_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_alternate_setting_locate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_channel_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_control_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_control_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_control_value_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_control_value_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_descriptor_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_format_data_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_frame_data_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_frame_interval_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_frame_parameters_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_input_format_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_input_terminal_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_max_payload_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_transfer_buffer_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_transfer_callback_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_transfer_request_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_bandwidth_check.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_bandwidth_claim.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_bandwidth_release.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_call.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_device_scan.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_instance_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_instance_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_instance_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_instance_verify.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_interface_scan.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_descriptor_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_enumerate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_instance_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_instance_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_interface_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_delay_ms.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_configuration_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_configuration_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_configuration_select.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_descriptor_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_remove.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_resources_free.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_endpoint_instance_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_endpoint_instance_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_endpoint_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_enum_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_hcd_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_hcd_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_hcd_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_hnp_polling_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interface_endpoint_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interface_instance_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interface_instance_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interface_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interface_setting_select.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interfaces_scan.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_new_configuration_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_new_device_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_new_device_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_new_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_new_interface_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_rh_change_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_rh_device_extraction.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_rh_device_insertion.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_role_swap.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_transfer_request_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_network_driver.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_system_error_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_system_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_system_uninitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_trace_event_insert.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_trace_event_update.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_trace_object_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_trace_object_unregister.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_debug_callback_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_debug_log.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_delay_ms.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_descriptor_pack.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_descriptor_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_error_callback_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_event_flags_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_event_flags_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_event_flags_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_event_flags_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_long_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_long_get_big_endian.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_long_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_long_put_big_endian.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_allocate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_compare.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_copy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_free.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_free_block_best_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_mutex_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_mutex_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_mutex_off.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_mutex_on.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_pci_class_scan.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_pci_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_pci_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_physical_address.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_semaphore_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_semaphore_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_semaphore_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_semaphore_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_set_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_short_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_short_get_big_endian.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_short_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_short_put_big_endian.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_string_length_check.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_string_length_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_string_to_unicode.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_identify.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_relinquish.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_schedule_other.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_sleep.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_timer_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_unicode_to_string.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_virtual_address.c + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/common/core/CMakeLists.txt b/common/core/CMakeLists.txt new file mode 100644 index 0000000..ce38377 --- /dev/null +++ b/common/core/CMakeLists.txt @@ -0,0 +1,208 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_endpoint_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_initialize_complete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_state_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_dcd_sim_slave_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dpump_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_alternate_setting_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_alternate_setting_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_class_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_class_unregister.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_clear_feature.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_configuration_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_configuration_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_control_request_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_descriptor_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_disconnect.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_endpoint_stall.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_get_status.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_host_wakeup.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_interface_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_interface_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_interface_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_interface_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_microsoft_extension_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_set_feature.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_transfer_all_request_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_stack_uninitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_asynch_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_asynch_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_ed_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_iso_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_iso_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_periodic_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_periodic_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_timer_function.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_transaction_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_sim_host_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_dpump_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_bandwidth_check.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_bandwidth_claim.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_bandwidth_release.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_call.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_device_scan.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_instance_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_instance_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_instance_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_instance_verify.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_interface_scan.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_class_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_descriptor_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_enumerate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_instance_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_instance_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_interface_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_configuration_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_delay_ms.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_address_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_configuration_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_configuration_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_configuration_select.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_descriptor_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_remove.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_device_resources_free.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_endpoint_instance_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_endpoint_instance_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_endpoint_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_enum_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_hcd_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_hcd_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_hcd_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_hnp_polling_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interface_endpoint_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interface_instance_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interface_instance_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interface_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interface_setting_select.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_interfaces_scan.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_new_configuration_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_new_device_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_new_device_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_new_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_new_interface_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_rh_change_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_rh_device_extraction.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_rh_device_insertion.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_role_swap.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_stack_transfer_request_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_system_error_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_system_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_system_uninitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_trace_event_insert.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_trace_event_update.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_trace_object_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_trace_object_unregister.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_debug_callback_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_debug_log.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_delay_ms.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_descriptor_pack.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_descriptor_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_error_callback_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_event_flags_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_event_flags_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_event_flags_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_event_flags_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_long_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_long_get_big_endian.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_long_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_long_put_big_endian.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_allocate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_allocate_add_safe.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_allocate_mulc_safe.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_allocate_mulv_safe.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_compare.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_copy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_free.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_free_block_best_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_memory_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_mutex_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_mutex_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_mutex_off.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_mutex_on.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_pci_class_scan.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_pci_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_pci_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_physical_address.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_semaphore_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_semaphore_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_semaphore_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_semaphore_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_set_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_short_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_short_get_big_endian.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_short_put.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_short_put_big_endian.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_string_length_check.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_string_length_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_string_to_unicode.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_identify.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_relinquish.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_schedule_other.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_sleep.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_thread_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_timer_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_unicode_to_string.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_utility_virtual_address.c + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/common/core/inc/ux_api.h b/common/core/inc/ux_api.h new file mode 100644 index 0000000..d528e9a --- /dev/null +++ b/common/core/inc/ux_api.h @@ -0,0 +1,1983 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Application Interface (API) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* APPLICATION INTERFACE DEFINITION RELEASE */ +/* */ +/* ux_api.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the basic Application Interface (API) to the */ +/* high-performance USBX real-time USB stack. All service prototypes */ +/* and data structure definitions are defined in this file. */ +/* Please note that basic data type definitions and other architecture-*/ +/* specific information is contained in the file ux_port.h. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_API_H +#define UX_API_H + +/* Determine if a C++ compiler is being used. If so, ensure that standard + C is used to process the API information. */ + +#ifdef __cplusplus + +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { + +#endif + + +/* Include ThreadX API include file. */ + +#include "tx_api.h" + + +/* Include USBX port specific file. */ + +#include "ux_port.h" + +/* Define the maximum length for class names (exclude string null-terminator). */ +#define UX_MAX_CLASS_NAME_LENGTH 63 + +/* Define the maximum length for HCD names (exclude string null-terminator). */ +#define UX_MAX_HCD_NAME_LENGTH 63 + +/* Disable warning of parameter not used. */ +#ifndef UX_PARAMETER_NOT_USED +#define UX_PARAMETER_NOT_USED(p) ((VOID)(p)) +#endif + +/* Define additional generic USBX types. */ + +#ifndef SCHAR +typedef signed char SCHAR; +#endif + +/* If the port file did not define the memory barrier instruction, define it + to nothing since this is platform-specific. */ +#ifndef UX_DATA_MEMORY_BARRIER +#define UX_DATA_MEMORY_BARRIER +#endif + + +/* This defines the ASSERT and process on ASSERT fail. */ +#ifdef UX_ENABLE_ASSERT +#ifndef UX_ASSERT_FAIL +#define UX_ASSERT_FAIL for (;;) {tx_thread_sleep(UX_WAIT_FOREVER); } +#endif +#define UX_ASSERT(s) if (!(s)) {UX_ASSERT_FAIL} +#else +#define UX_ASSERT(s) +#endif /* UX_ENABLE_ASSERT */ + + +#ifndef UX_MAX_SLAVE_INTERFACES +#define UX_MAX_SLAVE_INTERFACES 16 +#endif + +/* Convert from millisecond to ThreadX Tick value. */ +#define MS_TO_TICK(ms) ((ms) * (UX_PERIODIC_RATE) / 1000) + + +/* Define USBX Host Enum Thread Stack Size. */ +#ifndef UX_HOST_ENUM_THREAD_STACK_SIZE +#define UX_HOST_ENUM_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE +#endif + +/* Define USBX Host Thread Stack Size. */ +#ifndef UX_HOST_HCD_THREAD_STACK_SIZE +#define UX_HOST_HCD_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE +#endif + +/* Define USBX Host HNP Polling Thread Stack Size */ +#ifndef UX_HOST_HNP_POLLING_THREAD_STACK +#define UX_HOST_HNP_POLLING_THREAD_STACK UX_THREAD_STACK_SIZE +#endif + +/* Macros for concatenating tokens, where UX_CONCATn concatenates n tokens. */ + +#define UX_CONCAT_BASE(x,y) x ## y +#define UX_CONCAT2(s0,s1) UX_CONCAT_BASE(s0,s1) + +/* Static assert that can report an error at compile time. */ +#define UX_COMPILE_TIME_ASSERT(exp, meaningful_name_as_variable) \ + typedef char UX_CONCAT2(meaningful_name_as_variable, __LINE__)[!(exp) ? -1 : 1]; + +/* Arithmetics. */ + +#define UX_MIN(a, b) ((a) < (b) ? (a) : (b)) +#define UX_MAX(a, b) ((a) > (b) ? (a) : (b)) + +/* Safe arithmetic check macros. */ + +#ifndef UX_DISABLE_ARITHMETIC_CHECK + +/* Calculate and check if result overflow/underflow. */ + +#define UX_OVERFLOW_CHECK_ADD_ULONG(a, b) ((a) > 0xFFFFFFFFul - (b)) +#define UX_OVERFLOW_CHECK_ADD_USHORT(a, b) ((a) > 0xFFFFul - (b)) +#define UX_OVERFLOW_CHECK_ADD_UCHAR(a, b) ((a) > 0xFFul - (b)) + +#define UX_UNDERFLOW_CHECK_MINUS(a, b) ((a) < (b)) + +/* Overflow check optimized in case multiplying a 2nd factor of const. */ +#define UX_OVERFLOW_CHECK_MULC_ULONG(v, c) ((v) > 0xFFFFFFFFul / (c)) +#define UX_OVERFLOW_CHECK_MULC_USHORT(v, c) ((v) > 0xFFFFul / (c)) +#define UX_OVERFLOW_CHECK_MULC_UCHAR(v, c) ((v) > 0xFFul / (c)) + +/* Overflow check optimized in case multiplying factors of variables and division instruction unavailable. */ +#define UX_OVERFLOW_CHECK_MULV_ULONG(v, v1) ((v) * (v1) < UX_MIN(v, v1)) +#define UX_OVERFLOW_CHECK_MULV_USHORT(v, v1) ((USHORT)((v) * (v1)) < UX_MIN(v, v1)) +#define UX_OVERFLOW_CHECK_MULV_UCHAR(v, v1) ((UCHAR)((v) * (v1)) < UX_MIN(v, v1)) + +#else + +/* There is no overflow/underflow, always 0 (false). */ + +#define UX_OVERFLOW_CHECK_ADD_ULONG(a, b) (0) +#define UX_OVERFLOW_CHECK_ADD_USHORT(a, b) (0) +#define UX_OVERFLOW_CHECK_ADD_UCHAR(a, b) (0) + +#define UX_OVERFLOW_CHECK_MULC_ULONG(v, c) (0) +#define UX_OVERFLOW_CHECK_MULC_USHORT(v, c) (0) +#define UX_OVERFLOW_CHECK_MULC_UCHAR(v, c) (0) + +#define UX_OVERFLOW_CHECK_MULV_ULONG(v, v1) (0) +#define UX_OVERFLOW_CHECK_MULV_USHORT(v, v1) (0) +#define UX_OVERFLOW_CHECK_MULV_UCHAR(v, v1) (0) +#endif + +/* Define the default extension to hold the control block for 64-bit mode. */ + +#ifndef UX_THREAD_EXTENSION_PTR_SET +#define UX_THREAD_EXTENSION_PTR_SET(a, b) +#endif + +#ifndef UX_THREAD_EXTENSION_PTR_GET +#define UX_THREAD_EXTENSION_PTR_GET(a, b, c) (a) = (b *)(c); +#endif + +#ifndef UX_TIMER_EXTENSION_PTR_SET +#define UX_TIMER_EXTENSION_PTR_SET(a, b) +#endif + +#ifndef UX_TIMER_EXTENSION_PTR_GET +#define UX_TIMER_EXTENSION_PTR_GET(a, b, c) (a) = (b *)(c); +#endif + +/* Determine if error log is enabled. */ + +#ifdef UX_ENABLE_DEBUG_LOG + +#ifndef UX_DEBUG_LOG_SIZE +#define UX_DEBUG_LOG_SIZE (1024 * 32) +#endif + +/* Map the error log macros to internal USBX function. */ + +#define UX_DEBUG_LOG(debug_location, debug_message, debug_code, debug_parameter_1, debug_parameter_2) _ux_utility_debug_log((UCHAR *) debug_location, (UCHAR *) debug_message, (ULONG) debug_code, (ULONG) debug_parameter_1, (ULONG) debug_parameter_2); + +VOID _ux_utility_debug_log(UCHAR *debug_location, UCHAR *debug_message, ULONG debug_code, ULONG debug_parameter_1, ULONG debug_parameter_2); + +/* DEBUG LOG MESSAGES SHOULD BE WRITEN LIKE THIS IN THE CODE : */ +/* If error log is enabled, insert this error message into the log buffer. */ +/* UX_DEBUG_LOG("_ux_host_stack_rh_device_insertion", "Device insertion", port_index, port_index, 0) */ + + +#else + +/* If Log is not defined, map it to nothing so that debug messages can stay in the code. */ +#define UX_DEBUG_LOG(debug_location, debug_message, debug_code, debug_parameter_1, debug_parameter_2) +#endif + +/* Determine if tracing is enabled. */ + +#ifdef TX_ENABLE_EVENT_TRACE + +/* Trace is enabled. Remap calls so that interrupts can be disabled around the actual event logging. */ + +#include "tx_trace.h" + + +/* Map the trace macros to internal USBX versions so we can get interrupt protection. */ + +#define UX_TRACE_OBJECT_REGISTER(t,p,n,a,b) _ux_trace_object_register(t, (VOID *) p, (CHAR *) n, (ULONG) a, (ULONG) b); +#define UX_TRACE_OBJECT_UNREGISTER(o) _ux_trace_object_unregister((VOID *) o); +#define UX_TRACE_IN_LINE_INSERT(i,a,b,c,d,f,g,h) _ux_trace_event_insert((ULONG) i, (ULONG) a, (ULONG) b, (ULONG) c, (ULONG) d, (ULONG) f, g, h); +#define UX_TRACE_EVENT_UPDATE(e,t,i,a,b,c,d) _ux_trace_event_update((TX_TRACE_BUFFER_ENTRY *) e, (ULONG) t, (ULONG) i, (ULONG) a, (ULONG) b, (ULONG) c, (ULONG) d); + + +/* Define USBX trace prototypes. */ + +VOID _ux_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2); +VOID _ux_trace_object_unregister(VOID *object_ptr); +VOID _ux_trace_event_insert(ULONG event_id, ULONG info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4, ULONG filter, TX_TRACE_BUFFER_ENTRY **current_event, ULONG *current_timestamp); +VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, ULONG event_id, ULONG info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4); + + +/* Define USBX event trace constants. */ + +#define UX_TRACE_OBJECT_TYPE_BASE 20 +#define UX_TRACE_HOST_OBJECT_TYPE_DEVICE (UX_TRACE_OBJECT_TYPE_BASE + 1) +#define UX_TRACE_HOST_OBJECT_TYPE_INTERFACE (UX_TRACE_OBJECT_TYPE_BASE + 2) +#define UX_TRACE_HOST_OBJECT_TYPE_ENDPOINT (UX_TRACE_OBJECT_TYPE_BASE + 3) +#define UX_TRACE_HOST_OBJECT_TYPE_CLASS_INSTANCE (UX_TRACE_OBJECT_TYPE_BASE + 4) + +#define UX_TRACE_DEVICE_OBJECT_TYPE_DEVICE (UX_TRACE_OBJECT_TYPE_BASE + 5) +#define UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE (UX_TRACE_OBJECT_TYPE_BASE + 6) +#define UX_TRACE_DEVICE_OBJECT_TYPE_ENDPOINT (UX_TRACE_OBJECT_TYPE_BASE + 7) +#define UX_TRACE_DEVICE_OBJECT_TYPE_CLASS_INSTANCE (UX_TRACE_OBJECT_TYPE_BASE + 8) + +/* Define event filters that can be used to selectively disable certain events or groups of events. */ + +#define UX_TRACE_ALL_EVENTS 0x7F000000 /* All USBX events */ +#define UX_TRACE_ERRORS 0x01000000 /* USBX Errors events */ +#define UX_TRACE_HOST_STACK_EVENTS 0x02000000 /* USBX Host Class Events */ +#define UX_TRACE_DEVICE_STACK_EVENTS 0x04000000 /* USBX Device Class Events */ +#define UX_TRACE_HOST_CONTROLLER_EVENTS 0x08000000 /* USBX Host Controller Events */ +#define UX_TRACE_DEVICE_CONTROLLER_EVENTS 0x10000000 /* USBX Device Controllers Events */ +#define UX_TRACE_HOST_CLASS_EVENTS 0x20000000 /* USBX Host Class Events */ +#define UX_TRACE_DEVICE_CLASS_EVENTS 0x40000000 /* USBX Device Class Events */ + + +/* Define the trace events in USBX, if not defined. */ + +/* Define the USBX host stack events. */ + +#define UX_TRACE_HOST_STACK_EVENTS_BASE 600 +#define UX_TRACE_HOST_STACK_CLASS_INSTANCE_CREATE (UX_TRACE_HOST_STACK_EVENTS_BASE + 1) /* I1 = class , I2 = class instance */ +#define UX_TRACE_HOST_STACK_CLASS_INSTANCE_DESTROY (UX_TRACE_HOST_STACK_EVENTS_BASE + 2) /* I1 = class , I2 = class instance */ +#define UX_TRACE_HOST_STACK_CONFIGURATION_DELETE (UX_TRACE_HOST_STACK_EVENTS_BASE + 3) /* I1 = configuration */ +#define UX_TRACE_HOST_STACK_CONFIGURATION_ENUMERATE (UX_TRACE_HOST_STACK_EVENTS_BASE + 4) /* I1 = device */ +#define UX_TRACE_HOST_STACK_CONFIGURATION_INSTANCE_CREATE (UX_TRACE_HOST_STACK_EVENTS_BASE + 5) /* I1 = configuration */ +#define UX_TRACE_HOST_STACK_CONFIGURATION_INSTANCE_DELETE (UX_TRACE_HOST_STACK_EVENTS_BASE + 6) /* I1 = configuration */ +#define UX_TRACE_HOST_STACK_CONFIGURATION_SET (UX_TRACE_HOST_STACK_EVENTS_BASE + 7) /* I1 = configuration */ +#define UX_TRACE_HOST_STACK_DEVICE_ADDRESS_SET (UX_TRACE_HOST_STACK_EVENTS_BASE + 8) /* I1 = device , I2 = device address */ +#define UX_TRACE_HOST_STACK_DEVICE_CONFIGURATION_GET (UX_TRACE_HOST_STACK_EVENTS_BASE + 9) /* I1 = device , I2 = configuration */ +#define UX_TRACE_HOST_STACK_DEVICE_CONFIGURATION_SELECT (UX_TRACE_HOST_STACK_EVENTS_BASE + 10) /* I1 = device , I2 = configuration */ +#define UX_TRACE_HOST_STACK_DEVICE_DESCRIPTOR_READ (UX_TRACE_HOST_STACK_EVENTS_BASE + 11) /* I1 = device */ +#define UX_TRACE_HOST_STACK_DEVICE_GET (UX_TRACE_HOST_STACK_EVENTS_BASE + 12) /* I1 = device index */ +#define UX_TRACE_HOST_STACK_DEVICE_REMOVE (UX_TRACE_HOST_STACK_EVENTS_BASE + 13) /* I1 = hcd , I2 = parent , I3 = port index , I4 = device */ +#define UX_TRACE_HOST_STACK_DEVICE_RESOURCE_FREE (UX_TRACE_HOST_STACK_EVENTS_BASE + 14) /* I1 = device */ +#define UX_TRACE_HOST_STACK_ENDPOINT_INSTANCE_CREATE (UX_TRACE_HOST_STACK_EVENTS_BASE + 15) /* I1 = device , I2 = endpoint */ +#define UX_TRACE_HOST_STACK_ENDPOINT_INSTANCE_DELETE (UX_TRACE_HOST_STACK_EVENTS_BASE + 16) /* I1 = device , I2 = endpoint */ +#define UX_TRACE_HOST_STACK_ENDPOINT_RESET (UX_TRACE_HOST_STACK_EVENTS_BASE + 17) /* I1 = device , I2 = endpoint */ +#define UX_TRACE_HOST_STACK_ENDPOINT_TRANSFER_ABORT (UX_TRACE_HOST_STACK_EVENTS_BASE + 18) /* I1 = endpoint */ +#define UX_TRACE_HOST_STACK_HCD_REGISTER (UX_TRACE_HOST_STACK_EVENTS_BASE + 19) /* I1 = hcd name */ +#define UX_TRACE_HOST_STACK_INITIALIZE (UX_TRACE_HOST_STACK_EVENTS_BASE + 20) /* */ +#define UX_TRACE_HOST_STACK_INTERFACE_ENDPOINT_GET (UX_TRACE_HOST_STACK_EVENTS_BASE + 21) /* I1 = interface , I2 = endpoint index */ +#define UX_TRACE_HOST_STACK_INTERFACE_INSTANCE_CREATE (UX_TRACE_HOST_STACK_EVENTS_BASE + 22) /* I1 = interface */ +#define UX_TRACE_HOST_STACK_INTERFACE_INSTANCE_DELETE (UX_TRACE_HOST_STACK_EVENTS_BASE + 23) /* I1 = interface */ +#define UX_TRACE_HOST_STACK_INTERFACE_SET (UX_TRACE_HOST_STACK_EVENTS_BASE + 24) /* I1 = interface */ +#define UX_TRACE_HOST_STACK_INTERFACE_SETTING_SELECT (UX_TRACE_HOST_STACK_EVENTS_BASE + 25) /* I1 = interface */ +#define UX_TRACE_HOST_STACK_NEW_CONFIGURATION_CREATE (UX_TRACE_HOST_STACK_EVENTS_BASE + 26) /* I1 = device , I2 = configuration */ +#define UX_TRACE_HOST_STACK_NEW_DEVICE_CREATE (UX_TRACE_HOST_STACK_EVENTS_BASE + 27) /* I1 = hcd , I2 = device owner , I3 = port index , I4 = device */ +#define UX_TRACE_HOST_STACK_NEW_ENDPOINT_CREATE (UX_TRACE_HOST_STACK_EVENTS_BASE + 28) /* I1 = interface , I2 = endpoint */ +#define UX_TRACE_HOST_STACK_RH_CHANGE_PROCESS (UX_TRACE_HOST_STACK_EVENTS_BASE + 29) /* I1 = port index */ +#define UX_TRACE_HOST_STACK_RH_DEVICE_EXTRACTION (UX_TRACE_HOST_STACK_EVENTS_BASE + 30) /* I1 = hcd , I2 = port index */ +#define UX_TRACE_HOST_STACK_RH_DEVICE_INSERTION (UX_TRACE_HOST_STACK_EVENTS_BASE + 31) /* I1 = hcd , I2 = port index */ +#define UX_TRACE_HOST_STACK_TRANSFER_REQUEST (UX_TRACE_HOST_STACK_EVENTS_BASE + 32) /* I1 = device , I2 = endpoint , I3 = transfer request */ +#define UX_TRACE_HOST_STACK_TRANSFER_REQUEST_ABORT (UX_TRACE_HOST_STACK_EVENTS_BASE + 33) /* I1 = device , I2 = endpoint , I3 = transfer request */ + +/* Define the USBX host class events. */ + +#define UX_TRACE_HOST_CLASS_EVENTS_BASE 650 +#define UX_TRACE_HOST_CLASS_ASIX_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 1) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_ASIX_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 2) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_ASIX_INTERRUPT_NOTIFICATION (UX_TRACE_HOST_CLASS_EVENTS_BASE + 3) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_ASIX_READ (UX_TRACE_HOST_CLASS_EVENTS_BASE + 4) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_ASIX_WRITE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 5) /* I1 = class instance , I2 = data pointer , I3 = requested length */ + +#define UX_TRACE_HOST_CLASS_AUDIO_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 10) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_AUDIO_CONTROL_VALUE_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 11) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_AUDIO_CONTROL_VALUE_SET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 12) /* I1 = class instance , I2 = audio control */ +#define UX_TRACE_HOST_CLASS_AUDIO_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 13) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_AUDIO_READ (UX_TRACE_HOST_CLASS_EVENTS_BASE + 14) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_AUDIO_STREAMING_SAMPLING_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 15) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_AUDIO_STREAMING_SAMPLING_SET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 16) /* I1 = class instance , I2 = audio sampling */ +#define UX_TRACE_HOST_CLASS_AUDIO_WRITE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 17) /* I1 = class instance , I2 = data pointer , I3 = requested length */ + +#define UX_TRACE_HOST_CLASS_CDC_ACM_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 20) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 21) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING (UX_TRACE_HOST_CLASS_EVENTS_BASE + 22) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING (UX_TRACE_HOST_CLASS_EVENTS_BASE + 23) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 24) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_SEND_BREAK (UX_TRACE_HOST_CLASS_EVENTS_BASE + 25) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_ABORT_IN_PIPE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 26) /* I1 = class instance , I2 = endpoint */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_ABORT_OUT_PIPE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 27) /* I1 = class instance , I2 = endpointr */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_NOTIFICATION_CALLBACK (UX_TRACE_HOST_CLASS_EVENTS_BASE + 28) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_GET_DEVICE_STATUS (UX_TRACE_HOST_CLASS_EVENTS_BASE + 29) /* I1 = class instance , I2 = device status */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_READ (UX_TRACE_HOST_CLASS_EVENTS_BASE + 30) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_RECEPTION_START (UX_TRACE_HOST_CLASS_EVENTS_BASE + 31) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_RECEPTION_STOP (UX_TRACE_HOST_CLASS_EVENTS_BASE + 32) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_CDC_ACM_WRITE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 33) /* I1 = class instance , I2 = data pointer , I3 = requested length */ + +#define UX_TRACE_HOST_CLASS_CDC_ECM_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 35) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_CDC_ECM_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 36) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_CDC_ECM_READ (UX_TRACE_HOST_CLASS_EVENTS_BASE + 37) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_CDC_ECM_WRITE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 38) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_CDC_ECM_INTERRUPT_NOTIFICATION (UX_TRACE_HOST_CLASS_EVENTS_BASE + 39) /* I1 = class instance */ + +#define UX_TRACE_HOST_CLASS_HID_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 40) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_HID_CLIENT_REGISTER (UX_TRACE_HOST_CLASS_EVENTS_BASE + 41) /* I1 = hid client name */ +#define UX_TRACE_HOST_CLASS_HID_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 42) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_HID_IDLE_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 43) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_HID_IDLE_SET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 44) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_HID_KEYBOARD_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 45) /* I1 = class instance , I2 = hid client instance */ +#define UX_TRACE_HOST_CLASS_HID_KEYBOARD_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 46) /* I1 = class instance , I2 = hid client instance */ +#define UX_TRACE_HOST_CLASS_HID_MOUSE_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 47) /* I1 = class instance , I2 = hid client instance */ +#define UX_TRACE_HOST_CLASS_HID_MOUSE_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 48) /* I1 = class instance , I2 = hid client instance */ +#define UX_TRACE_HOST_CLASS_HID_REMOTE_CONTROL_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 49) /* I1 = class instance , I2 = hid client instance */ +#define UX_TRACE_HOST_CLASS_HID_REMOTE_CONTROL_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 50) /* I1 = class instance , I2 = hid client instance */ +#define UX_TRACE_HOST_CLASS_HID_REPORT_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 51) /* I1 = class instance , I2 = client report */ +#define UX_TRACE_HOST_CLASS_HID_REPORT_SET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 52) /* I1 = class instance , I2 = client report */ +#define UX_TRACE_HOST_CLASS_HID_REMOTE_CONTROL_CALLBACK (UX_TRACE_HOST_CLASS_EVENTS_BASE + 53) /* I1 = client instance , I2 = remote control instance */ + +#define UX_TRACE_HOST_CLASS_HUB_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 60) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_HUB_CHANGE_DETECT (UX_TRACE_HOST_CLASS_EVENTS_BASE + 62) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_HUB_PORT_CHANGE_CONNECTION_PROCESS (UX_TRACE_HOST_CLASS_EVENTS_BASE + 63) /* I1 = class instance , I2 = port , I3 = port status */ +#define UX_TRACE_HOST_CLASS_HUB_PORT_CHANGE_ENABLE_PROCESS (UX_TRACE_HOST_CLASS_EVENTS_BASE + 64) /* I1 = class instance , I2 = port , I3 = port status */ +#define UX_TRACE_HOST_CLASS_HUB_PORT_CHANGE_OVER_CURRENT_PROCESS (UX_TRACE_HOST_CLASS_EVENTS_BASE + 65) /* I1 = class instance , I2 = port , I3 = port status */ +#define UX_TRACE_HOST_CLASS_HUB_PORT_CHANGE_RESET_PROCESS (UX_TRACE_HOST_CLASS_EVENTS_BASE + 66) /* I1 = class instance , I2 = port , I3 = port status */ +#define UX_TRACE_HOST_CLASS_HUB_PORT_CHANGE_SUSPEND_PROCESS (UX_TRACE_HOST_CLASS_EVENTS_BASE + 67) /* I1 = class instance , I2 = port , I3 = port status */ +#define UX_TRACE_HOST_CLASS_HUB_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 68) /* I1 = class instance */ + +#define UX_TRACE_HOST_CLASS_PIMA_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 70) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PIMA_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 71) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PIMA_DEVICE_INFO_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 72) /* I1 = class instance , I2 = pima device */ +#define UX_TRACE_HOST_CLASS_PIMA_DEVICE_RESET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 73) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PIMA_NOTIFICATION (UX_TRACE_HOST_CLASS_EVENTS_BASE + 74) /* I1 = class instance , I2 = event code , I3 = transaction ID , I4 = parameter1 */ +#define UX_TRACE_HOST_CLASS_PIMA_NUM_OBJECTS_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 75) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PIMA_OBJECT_CLOSE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 76) /* I1 = class instance , I2 = object */ +#define UX_TRACE_HOST_CLASS_PIMA_OBJECT_COPY (UX_TRACE_HOST_CLASS_EVENTS_BASE + 77) /* I1 = class instance , I2 = object handle */ +#define UX_TRACE_HOST_CLASS_PIMA_OBJECT_DELETE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 78) /* I1 = class instance , I2 = object handle */ +#define UX_TRACE_HOST_CLASS_PIMA_OBJECT_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 79) /* I1 = class instance , I2 = object handle , I3 = object */ +#define UX_TRACE_HOST_CLASS_PIMA_OBJECT_INFO_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 80) /* I1 = class instance , I2 = object handle , I3 = object */ +#define UX_TRACE_HOST_CLASS_PIMA_OBJECT_INFO_SEND (UX_TRACE_HOST_CLASS_EVENTS_BASE + 81) /* I1 = class instance , I2 = object */ +#define UX_TRACE_HOST_CLASS_PIMA_OBJECT_MOVE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 82) /* I1 = class instance , I2 = object handle */ +#define UX_TRACE_HOST_CLASS_PIMA_OBJECT_SEND (UX_TRACE_HOST_CLASS_EVENTS_BASE + 83) /* I1 = class instance , I2 = object , I3 = object_buffer , I4 = object length */ +#define UX_TRACE_HOST_CLASS_PIMA_OBJECT_TRANSFER_ABORT (UX_TRACE_HOST_CLASS_EVENTS_BASE + 84) /* I1 = class instance , I2 = object handle , I3 = object */ +#define UX_TRACE_HOST_CLASS_PIMA_READ (UX_TRACE_HOST_CLASS_EVENTS_BASE + 85) /* I1 = class instance , I2 = data pointer , I3 = data length */ +#define UX_TRACE_HOST_CLASS_PIMA_REQUEST_CANCEL (UX_TRACE_HOST_CLASS_EVENTS_BASE + 86) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PIMA_SESSION_CLOSE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 87) /* I1 = class instance , I2 = pima session */ +#define UX_TRACE_HOST_CLASS_PIMA_SESSION_OPEN (UX_TRACE_HOST_CLASS_EVENTS_BASE + 88) /* I1 = class instance , I2 = pima session */ +#define UX_TRACE_HOST_CLASS_PIMA_STORAGE_IDS_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 89) /* I1 = class instance , I2 = storage ID array, I3 = storage ID length */ +#define UX_TRACE_HOST_CLASS_PIMA_STORAGE_INFO_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 90) /* I1 = class instance , I2 = storage ID , I3 = storage */ +#define UX_TRACE_HOST_CLASS_PIMA_THUMB_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 91) /* I1 = class instance , I2 = object handle */ +#define UX_TRACE_HOST_CLASS_PIMA_WRITE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 92) /* I1 = class instance , I2 = data pointer , I3 = data length */ + +#define UX_TRACE_HOST_CLASS_PRINTER_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 100) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PRINTER_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 101) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PRINTER_NAME_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 102) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PRINTER_READ (UX_TRACE_HOST_CLASS_EVENTS_BASE + 103) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_PRINTER_WRITE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 104) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_PRINTER_SOFT_RESET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 105) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PRINTER_STATUS_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 106) /* I1 = class instance , I2 = printer status */ + +#define UX_TRACE_HOST_CLASS_PROLIFIC_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 110) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 111) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_CODING (UX_TRACE_HOST_CLASS_EVENTS_BASE + 112) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_GET_LINE_CODING (UX_TRACE_HOST_CLASS_EVENTS_BASE + 113) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_STATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 114) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_PURGE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 115) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_SEND_BREAK (UX_TRACE_HOST_CLASS_EVENTS_BASE + 116) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_ABORT_IN_PIPE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 117) /* I1 = class instance , I2 = endpoint */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_ABORT_OUT_PIPE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 118) /* I1 = class instance , I2 = endpointr */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_REPORT_DEVICE_STATUS_CHANGE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 119) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_GET_DEVICE_STATUS (UX_TRACE_HOST_CLASS_EVENTS_BASE + 120) /* I1 = class instance , I2 = device status */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_READ (UX_TRACE_HOST_CLASS_EVENTS_BASE + 121) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_RECEPTION_START (UX_TRACE_HOST_CLASS_EVENTS_BASE + 122) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_RECEPTION_STOP (UX_TRACE_HOST_CLASS_EVENTS_BASE + 123) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_PROLIFIC_WRITE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 124) /* I1 = class instance , I2 = data pointer , I3 = requested length */ + +#define UX_TRACE_HOST_CLASS_STORAGE_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 130) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_STORAGE_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 131) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_STORAGE_MEDIA_CAPACITY_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 132) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_STORAGE_MEDIA_FORMAT_CAPACITY_GET (UX_TRACE_HOST_CLASS_EVENTS_BASE + 133) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_STORAGE_MEDIA_MOUNT (UX_TRACE_HOST_CLASS_EVENTS_BASE + 134) /* I1 = class instance , I2 = sector */ +#define UX_TRACE_HOST_CLASS_STORAGE_MEDIA_OPEN (UX_TRACE_HOST_CLASS_EVENTS_BASE + 135) /* I1 = class instance , I2 = media */ +#define UX_TRACE_HOST_CLASS_STORAGE_MEDIA_READ (UX_TRACE_HOST_CLASS_EVENTS_BASE + 136) /* I1 = class instance , I2 = sector start , I3 = sector count , I4 = data pointer */ +#define UX_TRACE_HOST_CLASS_STORAGE_MEDIA_WRITE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 137) /* I1 = class instance , I2 = sector start , I3 = sector count , I4 = data pointer */ +#define UX_TRACE_HOST_CLASS_STORAGE_REQUEST_SENSE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 138) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_STORAGE_START_STOP (UX_TRACE_HOST_CLASS_EVENTS_BASE + 139) /* I1 = class instance , I2 = start stop signal */ +#define UX_TRACE_HOST_CLASS_STORAGE_UNIT_READY_TEST (UX_TRACE_HOST_CLASS_EVENTS_BASE + 140) /* I1 = class instance */ + +#define UX_TRACE_HOST_CLASS_DPUMP_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 150) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_DPUMP_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 151) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_DPUMP_READ (UX_TRACE_HOST_CLASS_EVENTS_BASE + 152) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_DPUMP_WRITE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 153) /* I1 = class instance , I2 = data pointer , I3 = requested length */ + +#define UX_TRACE_HOST_CLASS_SWAR_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 160) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_SWAR_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 161) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_SWAR_IOCTL_ABORT_IN_PIPE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 162) /* I1 = class instance , I2 = endpoint */ +#define UX_TRACE_HOST_CLASS_SWAR_IOCTL_ABORT_OUT_PIPE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 163) /* I1 = class instance , I2 = endpointr */ +#define UX_TRACE_HOST_CLASS_SWAR_READ (UX_TRACE_HOST_CLASS_EVENTS_BASE + 164) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_SWAR_RECEPTION_START (UX_TRACE_HOST_CLASS_EVENTS_BASE + 165) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_SWAR_RECEPTION_STOP (UX_TRACE_HOST_CLASS_EVENTS_BASE + 166) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_SWAR_WRITE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 167) /* I1 = class instance , I2 = data pointer , I3 = requested length */ + +#define UX_TRACE_HOST_CLASS_GSER_ACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 170) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_GSER_DEACTIVATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 171) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_GSER_IOCTL_SET_LINE_CODING (UX_TRACE_HOST_CLASS_EVENTS_BASE + 172) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_GSER_IOCTL_GET_LINE_CODING (UX_TRACE_HOST_CLASS_EVENTS_BASE + 173) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_GSER_IOCTL_SET_LINE_STATE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 174) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_GSER_IOCTL_PURGE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 175) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_GSER_IOCTL_SEND_BREAK (UX_TRACE_HOST_CLASS_EVENTS_BASE + 176) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_GSER_IOCTL_ABORT_IN_PIPE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 177) /* I1 = class instance , I2 = endpoint */ +#define UX_TRACE_HOST_CLASS_GSER_IOCTL_ABORT_OUT_PIPE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 178) /* I1 = class instance , I2 = endpointr */ +#define UX_TRACE_HOST_CLASS_GSER_IOCTL_REPORT_DEVICE_STATUS_CHANGE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 179) /* I1 = class instance , I2 = parameter */ +#define UX_TRACE_HOST_CLASS_GSER_IOCTL_GET_DEVICE_STATUS (UX_TRACE_HOST_CLASS_EVENTS_BASE + 180) /* I1 = class instance , I2 = device status */ +#define UX_TRACE_HOST_CLASS_GSER_IOCTL_NOTIFICATION_CALLBACK (UX_TRACE_HOST_CLASS_EVENTS_BASE + 181) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_GSER_READ (UX_TRACE_HOST_CLASS_EVENTS_BASE + 182) /* I1 = class instance , I2 = data pointer , I3 = requested length */ +#define UX_TRACE_HOST_CLASS_GSER_RECEPTION_START (UX_TRACE_HOST_CLASS_EVENTS_BASE + 183) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_GSER_RECEPTION_STOP (UX_TRACE_HOST_CLASS_EVENTS_BASE + 184) /* I1 = class instance */ +#define UX_TRACE_HOST_CLASS_GSER_WRITE (UX_TRACE_HOST_CLASS_EVENTS_BASE + 185) /* I1 = class instance , I2 = data pointer , I3 = requested length */ + +/* Define the USBX device stack events. */ + +#define UX_TRACE_DEVICE_STACK_EVENTS_BASE 850 +#define UX_TRACE_DEVICE_STACK_ALTERNATE_SETTING_GET (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 1) /* I1 = interface value */ +#define UX_TRACE_DEVICE_STACK_ALTERNATE_SETTING_SET (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 2) /* I1 = interface value , I2 = alternate setting value */ +#define UX_TRACE_DEVICE_STACK_CLASS_REGISTER (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 3) /* I1 = class name , I2 = interface number, I3 = parameter */ +#define UX_TRACE_DEVICE_STACK_CLEAR_FEATURE (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 4) /* I1 = request type , I2 = request value , I3 = request index */ +#define UX_TRACE_DEVICE_STACK_CONFIGURATION_GET (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 5) /* I1 = configuration value */ +#define UX_TRACE_DEVICE_STACK_CONFIGURATION_SET (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 5) /* I1 = configuration value */ +#define UX_TRACE_DEVICE_STACK_CONNECT (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 6) /* */ +#define UX_TRACE_DEVICE_STACK_DESCRIPTOR_SEND (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 7) /* I1 = descriptor type , I2 = request index */ +#define UX_TRACE_DEVICE_STACK_DISCONNECT (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 8) /* I1 = device */ +#define UX_TRACE_DEVICE_STACK_ENDPOINT_STALL (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 9) /* I1 = endpoint */ +#define UX_TRACE_DEVICE_STACK_GET_STATUS (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 10) /* I1 = request type , I2 = request value , I3 = request index */ +#define UX_TRACE_DEVICE_STACK_HOST_WAKEUP (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 11) /* */ +#define UX_TRACE_DEVICE_STACK_INITIALIZE (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 12) /* */ +#define UX_TRACE_DEVICE_STACK_INTERFACE_DELETE (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 13) /* I1 = interface */ +#define UX_TRACE_DEVICE_STACK_INTERFACE_GET (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 14) /* I1 = interface value */ +#define UX_TRACE_DEVICE_STACK_INTERFACE_SET (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 15) /* I1 = alternate setting value */ +#define UX_TRACE_DEVICE_STACK_SET_FEATURE (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 16) /* I1 = request value , I2 = request index */ +#define UX_TRACE_DEVICE_STACK_TRANSFER_ABORT (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 17) /* I1 = transfer request, I2 = completion code */ +#define UX_TRACE_DEVICE_STACK_TRANSFER_ALL_REQUEST_ABORT (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 18) /* I1 = endpoint , I2 = completion code */ +#define UX_TRACE_DEVICE_STACK_TRANSFER_REQUEST (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 19) /* I1 = transfer request */ +#define UX_TRACE_DEVICE_STACK_MICROSOFT_EXTENSION_REGISTER (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 20) /* I1 = transfer request */ +#define UX_TRACE_DEVICE_STACK_CLASS_UNREGISTER (UX_TRACE_DEVICE_STACK_EVENTS_BASE + 21) /* I1 = class name */ + +/* Define the USBX device stack events first. */ + +#define UX_TRACE_DEVICE_CLASS_EVENTS_BASE 900 +#define UX_TRACE_DEVICE_CLASS_DPUMP_ACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 1) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_DPUMP_DEACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 2) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_DPUMP_READ (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 3) /* I1 = class instance , I2 = buffer , I3 = requested_length */ +#define UX_TRACE_DEVICE_CLASS_DPUMP_WRITE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 4) /* I1 = class instance , I2 = buffer , I3 = requested_length */ +#define UX_TRACE_DEVICE_CLASS_DPUMP_CHANGE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 4) /* I1 = class instance , I2 = buffer , I3 = requested_length */ + +#define UX_TRACE_DEVICE_CLASS_CDC_ACM_ACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 10) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_CDC_ACM_DEACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 11) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_CDC_ACM_READ (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 12) /* I1 = class instance , I2 = buffer , I3 = requested_length */ +#define UX_TRACE_DEVICE_CLASS_CDC_ACM_WRITE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 13) /* I1 = class instance , I2 = buffer , I3 = requested_length */ + +#define UX_TRACE_DEVICE_CLASS_HID_ACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 20) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_HID_DEACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 21) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_HID_EVENT_GET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 22) /* I1 = class instance , I2 = hid event */ +#define UX_TRACE_DEVICE_CLASS_HID_EVENT_SET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 23) /* I1 = class instance , I2 = hid event */ +#define UX_TRACE_DEVICE_CLASS_HID_REPORT_GET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 24) /* I1 = class instance , I2 = descriptor type , I3 = request index */ +#define UX_TRACE_DEVICE_CLASS_HID_REPORT_SET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 25) /* I1 = class instance , I2 = descriptor type , I3 = request index */ +#define UX_TRACE_DEVICE_CLASS_HID_DESCRIPTOR_SEND (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 26) /* I1 = class instance , I2 = descriptor type , I3 = request index */ + +#define UX_TRACE_DEVICE_CLASS_PIMA_ACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 30) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_DEACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 31) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_DEVICE_INFO_SEND (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 32) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_EVENT_GET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 33) /* I1 = class instance , I2 = pima event */ +#define UX_TRACE_DEVICE_CLASS_PIMA_EVENT_SET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 34) /* I1 = class instance , I2 = pima event */ +#define UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_ADD (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 35) /* I1 = class instance , I2 = object handle */ +#define UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_DATA_GET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 36) /* I1 = class instance , I2 = object handle */ +#define UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_DATA_SEND (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 37) /* I1 = class instance , I2 = object handle */ +#define UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_DELETE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 38) /* I1 = class instance , I2 = object handle */ +#define UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_HANDLES_SEND (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 39) /* I1 = class instance , I2 = storage id , I3 = object format code, I4 = object association */ +#define UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_INFO_GET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 40) /* I1 = class instance , I2 = object handle */ +#define UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_INFO_SEND (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 41) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_OBJECTS_NUMBER_SEND (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 42) /* I1 = class instance , I2 = storage id , I3 = object format code, I4 = object association */ +#define UX_TRACE_DEVICE_CLASS_PIMA_PARTIAL_OBJECT_DATA_GET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 43) /* I1 = class instance , I2 = object handle , I3 = offset requested , I4 = length requested */ +#define UX_TRACE_DEVICE_CLASS_PIMA_RESPONSE_SEND (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 44) /* I1 = class instance , I2 = response code , I3 = number parameter , I4 = pima parameter 1 */ +#define UX_TRACE_DEVICE_CLASS_PIMA_STORAGE_ID_SEND (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 45) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_STORAGE_INFO_SEND (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 46) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_GET_DEVICE_PROP_DESC_GET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 47) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_GET_DEVICE_PROP_VALUE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 48) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_GET_DEVICE_PROP_VALUE_SET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 49) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_GET_OBJECT_PROP_DESC (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 50) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_GET_OBJECT_PROP_VALUE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 51) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_OBJECTS_PROPS_SUPPORTED_GET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 52) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_GET_OBJECT_REFERENCES (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 53) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_OBJECTS_PROPS_SUPPORTED_SET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 54) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_SET_OBJECT_REFERENCES (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 55) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_STORAGE_FORMAT (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 56) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_DEVICE_RESET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 57) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_PIMA_SET_OBJECT_PROP_VALUE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 58) /* I1 = class instance */ + +#define UX_TRACE_DEVICE_CLASS_RNDIS_ACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 60) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_RNDIS_DEACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 61) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_RNDIS_PACKET_RECEIVE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 62) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_RNDIS_PACKET_TRANSMIT (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 63) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_RNDIS_MSG_QUERY (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 64) /* I1 = class instance , I2 = rndis OID */ +#define UX_TRACE_DEVICE_CLASS_RNDIS_MSG_KEEP_ALIVE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 65) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_RNDIS_MSG_RESET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 66) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_RNDIS_MSG_SET (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 67) /* I1 = class instance , I2 = rndis OID */ + +#define UX_TRACE_DEVICE_CLASS_STORAGE_ACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 70) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_DEACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 71) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_FORMAT (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 72) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_INQUIRY (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 73) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_MODE_SELECT (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 74) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_MODE_SENSE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 75) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_PREVENT_ALLOW_MEDIA_REMOVAL (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 76) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_READ (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 77) /* I1 = class instance , I2 = lun , I3 = sector , I4 = number sectors */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_READ_CAPACITY (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 78) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_READ_FORMAT_CAPACITY (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 79) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_READ_TOC (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 80) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_REQUEST_SENSE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 81) /* I1 = class instance , I2 = lun , I3 = sense key , I4 = code */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_TEST_READY (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 82) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_START_STOP (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 83) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_VERIFY (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 84) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_WRITE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 85) /* I1 = class instance , I2 = lun , I3 = sector , I4 = number sectors */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_GET_CONFIGURATION (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 86) /* I1 = class instance , I2 = lun */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_SYNCHRONIZE_CACHE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 87) /* I1 = class instance , I2 = lun , I3 = sector , I4 = number sectors */ +#define UX_TRACE_DEVICE_CLASS_STORAGE_OTHER (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 88) /* I1 = class instance , I2 = lun */ + +#define UX_TRACE_DEVICE_CLASS_CDC_ECM_ACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 90) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_CDC_ECM_DEACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 91) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_CDC_ECM_CHANGE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 92) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_CDC_ECM_READ (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 93) /* I1 = class instance , I2 = buffer , I3 = requested_length */ +#define UX_TRACE_DEVICE_CLASS_CDC_ECM_WRITE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 94) /* I1 = class instance , I2 = buffer , I3 = requested_length */ +#define UX_TRACE_DEVICE_CLASS_CDC_ECM_PACKET_TRANSMIT (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 95) /* I1 = class instance , I2 = buffer , I3 = requested_length */ +#define UX_TRACE_DEVICE_CLASS_CDC_ECM_PACKET_RECEIVE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 96) /* I1 = class instance , I2 = buffer , I3 = requested_length */ + +#define UX_TRACE_DEVICE_CLASS_DFU_ACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 97) /* I1 = class instance */ +#define UX_TRACE_DEVICE_CLASS_DFU_DEACTIVATE (UX_TRACE_DEVICE_CLASS_EVENTS_BASE + 98) /* I1 = class instance */ + +/* Define the USBX Error Event. */ + +#define UX_TRACE_ERROR 999 + + +#else +#define UX_TRACE_OBJECT_REGISTER(t,p,n,a,b) +#define UX_TRACE_OBJECT_UNREGISTER(o) +#define UX_TRACE_IN_LINE_INSERT(i,a,b,c,d,f,g,h) +#define UX_TRACE_EVENT_UPDATE(e,t,i,a,b,c,d) +#endif + + +/* Define the system level for error trapping. */ +#define UX_SYSTEM_LEVEL_INTERRUPT 1 +#define UX_SYSTEM_LEVEL_THREAD 2 + +/* Define the system context for error trapping. */ +#define UX_SYSTEM_CONTEXT_HCD 1 +#define UX_SYSTEM_CONTEXT_DCD 2 +#define UX_SYSTEM_CONTEXT_INIT 3 +#define UX_SYSTEM_CONTEXT_ENUMERATOR 4 +#define UX_SYSTEM_CONTEXT_ROOT_HUB 5 +#define UX_SYSTEM_CONTEXT_HUB 6 +#define UX_SYSTEM_CONTEXT_CLASS 7 +#define UX_SYSTEM_CONTEXT_UTILITY 8 +#define UX_SYSTEM_CONTEXT_DEVICE_STACK 9 + + +/* Defines the number of ThreadX timer ticks per seconds. By default, the ThreadX timer tick is 10ms, + so the default value for this constant is 100. If TX_TIMER_TICKS_PER_SECOND is defined, + this value is derived from TX_TIMER_TICKS_PER_SECOND. */ + +#ifndef UX_PERIODIC_RATE +#ifdef TX_TIMER_TICKS_PER_SECOND +#define UX_PERIODIC_RATE (TX_TIMER_TICKS_PER_SECOND) +#else +#define UX_PERIODIC_RATE 100 +#endif +#endif + +/* Define basic USBX constants. */ + +#define UX_NULL ((void*)0) +#define UX_TRUE 1 +#define UX_FALSE 0 +#define UX_MAX_TT 8 +#define UX_TT_MASK 0x1FF +#define UX_TT_BANDWIDTH 6000 +#define UX_SLAVE_ENDPOINT_DEFAULT_BUFFER_SIZE 256 +#define UX_REGULAR_MEMORY 0 +#define UX_CACHE_SAFE_MEMORY 1 + +#define UX_MAX_BYTES_PER_FRAME_FS 1157 +#define UX_MAX_BYTES_PER_MICROFRAME_HS 5785 + +/* Define USBX command request constants. */ + +#define UX_SETUP_REQUEST_TYPE 0 +#define UX_SETUP_REQUEST 1 +#define UX_SETUP_VALUE 2 +#define UX_SETUP_INDEX 4 +#define UX_SETUP_LENGTH 6 +#define UX_SETUP_SIZE 8 + + +/* Define USBX standard commands. */ + +#define UX_GET_STATUS 0 +#define UX_CLEAR_FEATURE 1 +#define UX_SET_FEATURE 3 +#define UX_SET_ADDRESS 5 +#define UX_GET_DESCRIPTOR 6 +#define UX_SET_DESCRIPTOR 7 +#define UX_GET_CONFIGURATION 8 +#define UX_SET_CONFIGURATION 9 +#define UX_GET_INTERFACE 10 +#define UX_SET_INTERFACE 11 +#define UX_SYNCH_FRAME 12 + + +/* Define USBX command sub constants. */ + +#define UX_ENDPOINT_HALT 0 + +/* Define USBX feature selector constants. */ +#define UX_REQUEST_FEATURE_ENDPOINT_HALT 0 +#define UX_REQUEST_FEATURE_DEVICE_REMOTE_WAKEUP 1 +#define UX_REQUEST_FEATURE_TEST_MODE 2 + +/* Define Generic USBX constants. */ + +#define UX_WAIT_FOREVER 0xffffffff +#define UX_UNUSED 0 +#define UX_USED 1 +#define UX_MEMORY_UNUSED 0x12345678 +#define UX_MEMORY_USED 0x87654321 +#define UX_NO_ALIGN 0 +#define UX_ALIGN_16 0x0f +#define UX_ALIGN_MIN 0x0f +#define UX_ALIGN_32 0x1f +#define UX_ALIGN_64 0x3f +#define UX_ALIGN_128 0x7f +#define UX_ALIGN_256 0xff +#define UX_ALIGN_512 0x1ff +#define UX_ALIGN_1024 0x3ff +#define UX_ALIGN_2048 0x7ff +#define UX_ALIGN_4096 0xfff +#define UX_SAFE_ALIGN 0xffffffff +#define UX_MAX_SCATTER_GATHER_ALIGNMENT 4096 + +#define UX_MAX_USB_DEVICES 127 + +#define UX_ENDPOINT_DIRECTION 0x80 +#define UX_ENDPOINT_IN 0x80 +#define UX_ENDPOINT_OUT 0x00 + +#define UX_MASK_ENDPOINT_TYPE 3 +#define UX_CONTROL_ENDPOINT 0 +#define UX_ISOCHRONOUS_ENDPOINT 1 +#define UX_BULK_ENDPOINT 2 +#define UX_INTERRUPT_ENDPOINT 3 + +#define UX_ISOCHRONOUS_ENDPOINT_IN 0x81 +#define UX_ISOCHRONOUS_ENDPOINT_OUT 0x01 +#define UX_BULK_ENDPOINT_IN 0x82 +#define UX_BULK_ENDPOINT_OUT 0x02 +#define UX_INTERRUPT_ENDPOINT_IN 0x83 +#define UX_INTERRUPT_ENDPOINT_OUT 0x03 + +#define UX_MAX_PACKET_SIZE_MASK 0x7ff +#define UX_MAX_NUMBER_OF_TRANSACTIONS_MASK 0x1800 +#define UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT 11 + +#define UX_REQUEST_DIRECTION 0x80 +#define UX_REQUEST_IN 0x80 +#define UX_REQUEST_OUT 0x00 + +#define UX_REQUEST_TYPE 0x60 +#define UX_REQUEST_TYPE_STANDARD 0x00 +#define UX_REQUEST_TYPE_CLASS 0x20 +#define UX_REQUEST_TYPE_VENDOR 0x40 + +#define UX_REQUEST_TARGET 0x03 +#define UX_REQUEST_TARGET_DEVICE 0x00 +#define UX_REQUEST_TARGET_INTERFACE 0x01 +#define UX_REQUEST_TARGET_ENDPOINT 0x02 +#define UX_REQUEST_TARGET_OTHER 0x03 + +#define UX_DEVICE_RESET 0 +#define UX_DEVICE_ATTACHED 1 +#define UX_DEVICE_ADDRESSED 2 +#define UX_DEVICE_CONFIGURED 3 +#define UX_DEVICE_SUSPENDED 4 +#define UX_DEVICE_RESUMED 5 +#define UX_DEVICE_SELF_POWERED_STATE 6 +#define UX_DEVICE_BUS_POWERED_STATE 7 +#define UX_DEVICE_REMOTE_WAKEUP 8 +#define UX_DEVICE_BUS_RESET_COMPLETED 9 +#define UX_DEVICE_REMOVED 10 +#define UX_DEVICE_FORCE_DISCONNECT 11 + +#define UX_ENDPOINT_RESET 0 +#define UX_ENDPOINT_RUNNING 1 +#define UX_ENDPOINT_HALTED 2 + +#define UX_DEVICE_DESCRIPTOR_ITEM 1 +#define UX_CONFIGURATION_DESCRIPTOR_ITEM 2 +#define UX_STRING_DESCRIPTOR_ITEM 3 +#define UX_INTERFACE_DESCRIPTOR_ITEM 4 +#define UX_ENDPOINT_DESCRIPTOR_ITEM 5 +#define UX_DEVICE_QUALIFIER_DESCRIPTOR_ITEM 6 +#define UX_OTHER_SPEED_DESCRIPTOR_ITEM 7 +#define UX_OTG_DESCRIPTOR_ITEM 9 +#define UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ITEM 11 +#define UX_DFU_FUNCTIONAL_DESCRIPTOR_ITEM 0x21 +#define UX_HUB_DESCRIPTOR_ITEM 0x29 + + +#define UX_CONTROL_TRANSFER_TIMEOUT 1000 +#define UX_NON_CONTROL_TRANSFER_TIMEOUT 5000 +#define UX_PORT_ENABLE_WAIT 50 +#define UX_DEVICE_ADDRESS_SET_WAIT 50 +#define UX_HIGH_SPEED_DETECTION_HANDSHAKE_SUSPEND_WAIT 200 +#define UX_ENUMERATION_THREAD_WAIT 200 + + +/* USBX 5.8 BACKWARD COMPATIBILITY DEFINITIONS. THESE DEFINITIONS ARE NOW OBSOLETE + BUT DEFINED HERE FOR COMPATIBILITY REASONS. */ + +#ifndef UX_CONTROL_TRANSFER_TIMEOUT_IN_MS +#define UX_CONTROL_TRANSFER_TIMEOUT_IN_MS 10000 +#endif + +#ifndef UX_NON_CONTROL_TRANSFER_TIMEOUT_IN_MS +#define UX_NON_CONTROL_TRANSFER_TIMEOUT_IN_MS 50000 +#endif + +#ifndef UX_PORT_ENABLE_WAIT_IN_MS +#define UX_PORT_ENABLE_WAIT_IN_MS 500 +#endif + +#ifndef UX_DEVICE_ADDRESS_SET_WAIT_IN_MS +#define UX_DEVICE_ADDRESS_SET_WAIT_IN_MS 500 +#endif + +#ifndef UX_HIGH_SPEED_DETECTION_HANDSHAKE_SUSPEND_WAIT_IN_MS +#define UX_HIGH_SPEED_DETECTION_HANDSHAKE_SUSPEND_WAIT_IN_MS 2000 +#endif + +/* END OF 5.8 BACKWARD COMPATIBILITY DEFINITIONS. */ + +#define UX_TRANSFER_PHASE_SETUP 1 +#define UX_TRANSFER_PHASE_DATA_IN 2 +#define UX_TRANSFER_PHASE_DATA_OUT 3 +#define UX_TRANSFER_PHASE_STATUS_IN 4 +#define UX_TRANSFER_PHASE_STATUS_OUT 5 + +#define UX_DEVICE_INSERTION 1 +#define UX_DEVICE_REMOVAL 2 +#define UX_HID_CLIENT_INSERTION 3 +#define UX_HID_CLIENT_REMOVAL 4 + + +/* Define USBX transfer request status constants. */ + +#define UX_TRANSFER_STATUS_NOT_PENDING 0 +#define UX_TRANSFER_STATUS_PENDING 1 +#define UX_TRANSFER_STATUS_COMPLETED 2 +#define UX_TRANSFER_STATUS_ABORT 4 + +/* Define USBX device power constants. */ + +#define UX_DEVICE_BUS_POWERED 1 +#define UX_DEVICE_SELF_POWERED 2 +#define UX_MAX_SELF_POWER (500/2) +#define UX_MAX_BUS_POWER (100/2) +#define UX_CONFIGURATION_DEVICE_BUS_POWERED 0x80 +#define UX_CONFIGURATION_DEVICE_SELF_POWERED 0x40 +#define UX_STATUS_DEVICE_SELF_POWERED 1 + +/* Define USBX OTG constants. */ + +#define UX_OTG_BM_ATTRIBUTES 2 +#define UX_OTG_SRP_SUPPORT 1 +#define UX_OTG_HNP_SUPPORT 2 +#define UX_HCD_OTG_CAPABLE 1 +#define UX_DCD_OTG_CAPABLE 1 + +#define UX_OTG_FEATURE_B_HNP_ENABLE 3 +#define UX_OTG_FEATURE_A_HNP_SUPPORT 4 +#define UX_OTG_FEATURE_A_ALT_HNP_SUPPORT 5 +#define UX_OTG_STATUS_SELECTOR 0xF000 +#define UX_OTG_HOST_REQUEST_FLAG 0x01 + +#define UX_OTG_IDLE 0 +#define UX_OTG_IDLE_TO_HOST 1 +#define UX_OTG_IDLE_TO_SLAVE 2 +#define UX_OTG_HOST_TO_IDLE 3 +#define UX_OTG_HOST_TO_SLAVE 4 +#define UX_OTG_SLAVE_TO_IDLE 5 +#define UX_OTG_SLAVE_TO_HOST 6 +#define UX_OTG_SLAVE_SRP 7 + +#define UX_OTG_MODE_IDLE 0 +#define UX_OTG_MODE_SLAVE 1 +#define UX_OTG_MODE_HOST 2 + +#define UX_OTG_DEVICE_IDLE 0 +#define UX_OTG_DEVICE_A 1 +#define UX_OTG_DEVICE_B 2 + +#define UX_OTG_VBUS_IDLE 0 +#define UX_OTG_VBUS_ON 1 +#define UX_OTG_VBUS_OFF 2 + + +#define UX_OTG_HNP_THREAD_SLEEP_TIME (2 * UX_PERIODIC_RATE) + +/* Define USBX device speed constants. */ + +#define UX_DEFAULT_HS_MPS 64 +#define UX_DEFAULT_MPS 8 + +#define UX_LOW_SPEED_DEVICE 0 +#define UX_FULL_SPEED_DEVICE 1 +#define UX_HIGH_SPEED_DEVICE 2 + + +/* Define USBX generic port status constants. */ + +#define UX_PS_CCS 0x01 +#define UX_PS_CPE 0x01 +#define UX_PS_PES 0x02 +#define UX_PS_PSS 0x04 +#define UX_PS_POCI 0x08 +#define UX_PS_PRS 0x10 +#define UX_PS_PPS 0x20 +#define UX_PS_DS_LS 0x00 +#define UX_PS_DS_FS 0x40 +#define UX_PS_DS_HS 0x80 + +#define UX_PS_DS 6 + + +/* Define USBX Error Code constants. The following format describes + their meaning: + + 0x1x : Configuration errors + 0x2x : USB transport errors + 0x3x : USB controller errors + 0x4x : USB topology errors + 0x5x : USB API errors + 0x6x : USB Generic Class errors + 0x7x : USB HID Class errors + 0x8x : USB Audio Class errors + 0x9x : USB CDC-ECM Class errors +*/ + +#define UX_SUCCESS 0 +#define UX_ERROR 0xff +#define UX_TOO_MANY_DEVICES 0x11 +#define UX_MEMORY_INSUFFICIENT 0x12 +#define UX_NO_TD_AVAILABLE 0x13 +#define UX_NO_ED_AVAILABLE 0x14 +#define UX_SEMAPHORE_ERROR 0x15 +#define UX_THREAD_ERROR 0x16 +#define UX_MUTEX_ERROR 0x17 +#define UX_EVENT_ERROR 0x18 +#define UX_MEMORY_CORRUPTED 0x19 +#define UX_MEMORY_ARRAY_FULL 0x1a +#define UX_FATAL_ERROR 0x1b + +#define UX_TRANSFER_STALLED 0x21 +#define UX_TRANSFER_NO_ANSWER 0x22 +#define UX_TRANSFER_ERROR 0x23 +#define UX_TRANSFER_MISSED_FRAME 0x24 +#define UX_TRANSFER_NOT_READY 0x25 +#define UX_TRANSFER_BUS_RESET 0x26 +#define UX_TRANSFER_BUFFER_OVERFLOW 0x27 +#define UX_TRANSFER_APPLICATION_RESET 0x28 +#define UX_TRANSFER_DATA_LESS_THAN_EXPECTED 0x29 + +#define UX_PORT_RESET_FAILED 0x31 +#define UX_CONTROLLER_INIT_FAILED 0x32 +#define UX_CONTROLLER_DEAD 0x33 + +#define UX_NO_BANDWIDTH_AVAILABLE 0x41 +#define UX_DESCRIPTOR_CORRUPTED 0x42 +#define UX_OVER_CURRENT_CONDITION 0x43 +#define UX_DEVICE_ENUMERATION_FAILURE 0x44 + +#define UX_DEVICE_HANDLE_UNKNOWN 0x50 +#define UX_CONFIGURATION_HANDLE_UNKNOWN 0x51 +#define UX_INTERFACE_HANDLE_UNKNOWN 0x52 +#define UX_ENDPOINT_HANDLE_UNKNOWN 0x53 +#define UX_FUNCTION_NOT_SUPPORTED 0x54 +#define UX_CONTROLLER_UNKNOWN 0x55 +#define UX_PORT_INDEX_UNKNOWN 0x56 +#define UX_NO_CLASS_MATCH 0x57 +#define UX_HOST_CLASS_ALREADY_INSTALLED 0x58 +#define UX_HOST_CLASS_UNKNOWN 0x59 +#define UX_CONNECTION_INCOMPATIBLE 0x5a +#define UX_HOST_CLASS_INSTANCE_UNKNOWN 0x5b +#define UX_TRANSFER_TIMEOUT 0x5c +#define UX_BUFFER_OVERFLOW 0x5d +#define UX_NO_ALTERNATE_SETTING 0x5e +#define UX_NO_DEVICE_CONNECTED 0x5f + +#define UX_HOST_CLASS_PROTOCOL_ERROR 0x60 +#define UX_HOST_CLASS_MEMORY_ERROR 0x61 +#define UX_HOST_CLASS_MEDIA_NOT_SUPPORTED 0x62 +#define UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR 0x63 + +#define UX_HOST_CLASS_HID_REPORT_OVERFLOW 0x70 +#define UX_HOST_CLASS_HID_USAGE_OVERFLOW 0x71 +#define UX_HOST_CLASS_HID_TAG_UNSUPPORTED 0x72 +#define UX_HOST_CLASS_HID_PUSH_OVERFLOW 0x73 +#define UX_HOST_CLASS_HID_POP_UNDERFLOW 0x74 +#define UX_HOST_CLASS_HID_COLLECTION_OVERFLOW 0x75 +#define UX_HOST_CLASS_HID_COLLECTION_UNDERFLOW 0x76 +#define UX_HOST_CLASS_HID_MIN_MAX_ERROR 0x77 +#define UX_HOST_CLASS_HID_DELIMITER_ERROR 0x78 +#define UX_HOST_CLASS_HID_REPORT_ERROR 0x79 +#define UX_HOST_CLASS_HID_PERIODIC_REPORT_ERROR 0x7A +#define UX_HOST_CLASS_HID_UNKNOWN 0x7B + +#define UX_HOST_CLASS_AUDIO_WRONG_TYPE 0x80 +#define UX_HOST_CLASS_AUDIO_WRONG_INTERFACE 0x81 + +#define UX_CLASS_CDC_ECM_LINK_STATE_DOWN_ERROR 0x90 + + +/* Define USBX HCD API function constants. */ + +#define UX_HCD_DISABLE_CONTROLLER 1 +#define UX_HCD_GET_PORT_STATUS 2 +#define UX_HCD_ENABLE_PORT 3 +#define UX_HCD_DISABLE_PORT 4 +#define UX_HCD_POWER_ON_PORT 5 +#define UX_HCD_POWER_DOWN_PORT 6 +#define UX_HCD_SUSPEND_PORT 7 +#define UX_HCD_RESUME_PORT 8 +#define UX_HCD_RESET_PORT 9 +#define UX_HCD_GET_FRAME_NUMBER 10 +#define UX_HCD_SET_FRAME_NUMBER 11 +#define UX_HCD_TRANSFER_REQUEST 12 +#define UX_HCD_TRANSFER_ABORT 13 +#define UX_HCD_CREATE_ENDPOINT 14 +#define UX_HCD_DESTROY_ENDPOINT 15 +#define UX_HCD_RESET_ENDPOINT 16 +#define UX_HCD_PROCESS_DONE_QUEUE 17 + +/* Define USBX DCD API function constants. */ + +#define UX_DCD_DISABLE_CONTROLLER 1 +#define UX_DCD_GET_PORT_STATUS 2 +#define UX_DCD_ENABLE_PORT 3 +#define UX_DCD_DISABLE_PORT 4 +#define UX_DCD_POWER_ON_PORT 5 +#define UX_DCD_POWER_DOWN_PORT 6 +#define UX_DCD_SUSPEND_PORT 7 +#define UX_DCD_RESUME_PORT 8 +#define UX_DCD_RESET_PORT 9 +#define UX_DCD_GET_FRAME_NUMBER 10 +#define UX_DCD_SET_FRAME_NUMBER 11 +#define UX_DCD_TRANSFER_REQUEST 12 +#define UX_DCD_TRANSFER_ABORT 13 +#define UX_DCD_CREATE_ENDPOINT 14 +#define UX_DCD_DESTROY_ENDPOINT 15 +#define UX_DCD_RESET_ENDPOINT 16 +#define UX_DCD_SET_DEVICE_ADDRESS 17 +#define UX_DCD_ISR_PENDING 18 +#define UX_DCD_CHANGE_STATE 19 +#define UX_DCD_STALL_ENDPOINT 20 +#define UX_DCD_ENDPOINT_STATUS 21 + + +/* Define USBX generic host controller constants. */ + +#define UX_HCD_STATUS_HALTED 0 +#define UX_HCD_STATUS_OPERATIONAL 1 +#define UX_HCD_STATUS_DEAD 2 + +/* Define USBX generic SLAVE controller constants. */ + +#define UX_DCD_STATUS_HALTED 0 +#define UX_DCD_STATUS_OPERATIONAL 1 +#define UX_DCD_STATUS_DEAD 2 + +/* Define USBX SLAVE controller VBUS constants. */ + +#define UX_DCD_VBUS_RESET 0 +#define UX_DCD_VBUS_SET 1 + +/* Define USBX class interface constants. */ + +#define UX_HOST_CLASS_COMMAND_QUERY 1 +#define UX_HOST_CLASS_COMMAND_ACTIVATE 2 +#define UX_HOST_CLASS_COMMAND_DEACTIVATE 3 + +#define UX_SLAVE_CLASS_COMMAND_QUERY 1 +#define UX_SLAVE_CLASS_COMMAND_ACTIVATE 2 +#define UX_SLAVE_CLASS_COMMAND_DEACTIVATE 3 +#define UX_SLAVE_CLASS_COMMAND_REQUEST 4 +#define UX_SLAVE_CLASS_COMMAND_INITIALIZE 5 +#define UX_SLAVE_CLASS_COMMAND_CHANGE 6 +#define UX_SLAVE_CLASS_COMMAND_UNINITIALIZE 7 + +#define UX_HOST_CLASS_COMMAND_USAGE_PIDVID 1 +#define UX_HOST_CLASS_COMMAND_USAGE_CSP 2 + +#define UX_HOST_CLASS_INSTANCE_FREE 0 +#define UX_HOST_CLASS_INSTANCE_LIVE 1 +#define UX_HOST_CLASS_INSTANCE_SHUTDOWN 2 +#define UX_HOST_CLASS_INSTANCE_MOUNTING 3 + + +/* Define USBX root HUB constants. */ + +#define UX_RH_ENUMERATION_RETRY 3 +#define UX_RH_ENUMERATION_RETRY_DELAY 100 + + +/* Define USBX PCI driver constants. */ + +#define UX_PCI_NB_FUNCTIONS 7 +#define UX_PCI_NB_DEVICE 32 +#define UX_PCI_NB_BUS 0xff + +#define UX_PCI_CMD_IO_ENABLE 0x0001 +#define UX_PCI_CMD_MEM_ENABLE 0x0002 +#define UX_PCI_CMD_MASTER_ENABLE 0x0004 +#define UX_PCI_CMD_MONITOR_ENABLE 0x0008 +#define UX_PCI_CMD_MEM_WRITE_INV_ENABLE 0x0010 +#define UX_PCI_CMD_SNOOP_PALETTE_ENABLE 0x0020 +#define UX_PCI_CMD_PARITY_ERROR_ENABLE 0x0040 +#define UX_PCI_CMD_WAIT_CYCLE_CTRL_ENABLE 0x0080 +#define UX_PCI_CMD_SERR_ENABLE 0x0100 +#define UX_PCI_CMD_FBB_ENABLE 0x0200 + +#define UX_PCI_CFG_CTRL_ADDRESS 0x0cf8 +#define UX_PCI_CFG_DATA_ADDRESS 0x0cfc + +#define UX_PCI_CFG_VENDOR_ID 0x00 +#define UX_PCI_CFG_DEVICE_ID 0x02 +#define UX_PCI_CFG_COMMAND 0x04 +#define UX_PCI_CFG_STATUS 0x06 +#define UX_PCI_CFG_REVISION 0x08 +#define UX_PCI_CFG_PROGRAMMING_IF 0x09 +#define UX_PCI_CFG_SUBCLASS 0x0a +#define UX_PCI_CFG_CLASS 0x0b +#define UX_PCI_CFG_CACHE_LINE_SIZE 0x0c +#define UX_PCI_CFG_LATENCY_TIMER 0x0d +#define UX_PCI_CFG_HEADER_TYPE 0x0e +#define UX_PCI_CFG_BIST 0x0f +#define UX_PCI_CFG_BASE_ADDRESS_0 0x10 +#define UX_PCI_CFG_BASE_ADDRESS_1 0x14 +#define UX_PCI_CFG_BASE_ADDRESS_2 0x18 +#define UX_PCI_CFG_BASE_ADDRESS_3 0x1c +#define UX_PCI_CFG_BASE_ADDRESS_4 0x20 +#define UX_PCI_CFG_BASE_ADDRESS_5 0x24 +#define UX_PCI_CFG_CARDBUS_CIS 0x28 +#define UX_PCI_CFG_SUB_VENDOR_ID 0x2c +#define UX_PCI_CFG_SUB_SYSTEM_ID 0x2e +#define UX_PCI_CFG_EXPANSION_ROM_ADDRESS 0x30 +#define UX_PCI_CFG_RESERVED_0 0x34 +#define UX_PCI_CFG_RESERVED_1 0x38 +#define UX_PCI_CFG_INT_LINE 0x3c +#define UX_PCI_CFG_INT_PIN 0x3d +#define UX_PCI_CFG_MIN_GNT 0x3e +#define UX_PCI_CFG_MAX_LATENCY 0x3f + +#define UX_PCI_CFG_SBRN 0x60 +#define UX_PCI_CFG_FLADJ 0x61 + +/* Define DFU constants. */ +#define UX_SYSTEM_DFU_STATE_APP_IDLE 0 +#define UX_SYSTEM_DFU_STATE_APP_DETACH 1 +#define UX_SYSTEM_DFU_STATE_DFU_IDLE 2 +#define UX_SYSTEM_DFU_STATE_DFU_DNLOAD_SYNC 3 +#define UX_SYSTEM_DFU_STATE_DFU_DNBUSY 4 +#define UX_SYSTEM_DFU_STATE_DFU_DNLOAD_IDLE 5 +#define UX_SYSTEM_DFU_STATE_DFU_MANIFEST_SYNC 6 +#define UX_SYSTEM_DFU_STATE_DFU_MANIFEST 7 +#define UX_SYSTEM_DFU_STATE_DFU_MANIFEST_WAIT_RESET 8 +#define UX_SYSTEM_DFU_STATE_DFU_UPLOAD_IDLE 9 +#define UX_SYSTEM_DFU_STATE_DFU_ERROR 10 + +/* Define basic class constants. */ + +#define UX_HOST_CLASS_PRINTER_NAME_LENGTH 64 + + +/* Define USBX 2.0 TT Instance structure. */ + +typedef struct UX_HUB_TT_STRUCT +{ + + ULONG ux_hub_tt_port_mapping; + ULONG ux_hub_tt_max_bandwidth; +} UX_HUB_TT; + + +/* Define USBX Class calling command structure. */ + +typedef struct UX_HOST_CLASS_COMMAND_STRUCT +{ + + UINT ux_host_class_command_request; + VOID *ux_host_class_command_container; + VOID *ux_host_class_command_instance; + UINT ux_host_class_command_usage; + UINT ux_host_class_command_pid; + UINT ux_host_class_command_vid; + UINT ux_host_class_command_class; + UINT ux_host_class_command_subclass; + UINT ux_host_class_command_protocol; + UINT ux_host_class_command_iad_class; + UINT ux_host_class_command_iad_subclass; + UINT ux_host_class_command_iad_protocol; + + struct UX_HOST_CLASS_STRUCT + *ux_host_class_command_class_ptr; +} UX_HOST_CLASS_COMMAND; + + +/* Define USBX Class container structure. */ + +typedef struct UX_HOST_CLASS_STRUCT +{ + + UCHAR ux_host_class_name[UX_MAX_CLASS_NAME_LENGTH + 1]; /* "+1" for string null-terminator */ + UINT ux_host_class_status; + UINT (*ux_host_class_entry_function) (struct UX_HOST_CLASS_COMMAND_STRUCT *) ; + UINT ux_host_class_nb_devices_owned; + VOID *ux_host_class_first_instance; + VOID *ux_host_class_client; + TX_THREAD ux_host_class_thread; + VOID *ux_host_class_thread_stack; + VOID *ux_host_class_media; +} UX_HOST_CLASS; + + +/* Define USBX transfer request structure. */ + +typedef struct UX_TRANSFER_STRUCT +{ + + ULONG ux_transfer_request_status; + struct UX_ENDPOINT_STRUCT + *ux_transfer_request_endpoint; + UCHAR * ux_transfer_request_data_pointer; + ULONG ux_transfer_request_requested_length; + ULONG ux_transfer_request_actual_length; + UINT ux_transfer_request_type; + UINT ux_transfer_request_function; + UINT ux_transfer_request_value; + UINT ux_transfer_request_index; + VOID (*ux_transfer_request_completion_function) (struct UX_TRANSFER_STRUCT *); + TX_SEMAPHORE ux_transfer_request_semaphore; + VOID *ux_transfer_request_class_instance; + ULONG ux_transfer_request_maximum_length; + ULONG ux_transfer_request_timeout_value; + UINT ux_transfer_request_completion_code; + ULONG ux_transfer_request_packet_length; + struct UX_TRANSFER_STRUCT + *ux_transfer_request_next_transfer_request; + VOID *ux_transfer_request_user_specific; + TX_THREAD *ux_transfer_request_thread_pending; +} UX_TRANSFER; + + +/* Define USBX Endpoint Descriptor structure. */ + +typedef struct UX_ENDPOINT_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bEndpointAddress; + ULONG bmAttributes; + ULONG wMaxPacketSize; + ULONG bInterval; +} UX_ENDPOINT_DESCRIPTOR; + +#define UX_ENDPOINT_DESCRIPTOR_ENTRIES 6 +#define UX_ENDPOINT_DESCRIPTOR_LENGTH 7 + + +/* Define USBX Endpoint Container structure. */ + +typedef struct UX_ENDPOINT_STRUCT +{ + + ULONG ux_endpoint; + ULONG ux_endpoint_state; + void *ux_endpoint_ed; + struct UX_ENDPOINT_DESCRIPTOR_STRUCT + ux_endpoint_descriptor; + struct UX_ENDPOINT_STRUCT + *ux_endpoint_next_endpoint; + struct UX_INTERFACE_STRUCT + *ux_endpoint_interface; + struct UX_DEVICE_STRUCT + *ux_endpoint_device; + struct UX_TRANSFER_STRUCT + ux_endpoint_transfer_request; +} UX_ENDPOINT; + + +/* Define USBX Device Descriptor structure. */ + +typedef struct UX_DEVICE_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bcdUSB; + ULONG bDeviceClass; + ULONG bDeviceSubClass; + ULONG bDeviceProtocol; + ULONG bMaxPacketSize0; + ULONG idVendor; + ULONG idProduct; + ULONG bcdDevice; + ULONG iManufacturer; + ULONG iProduct; + ULONG iSerialNumber; + ULONG bNumConfigurations; +} UX_DEVICE_DESCRIPTOR; + +#define UX_DEVICE_DESCRIPTOR_ENTRIES 14 +#define UX_DEVICE_DESCRIPTOR_LENGTH 18 + +/* Define USBX Device Qualifier Descriptor structure. */ + +typedef struct UX_DEVICE_QUALIFIER_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bcdUSB; + ULONG bDeviceClass; + ULONG bDeviceSubClass; + ULONG bDeviceProtocol; + ULONG bMaxPacketSize0; + ULONG bNumConfigurations; + ULONG bReserved; +} UX_DEVICE_QUALIFIER_DESCRIPTOR; + +#define UX_DEVICE_QUALIFIER_DESCRIPTOR_ENTRIES 9 +#define UX_DEVICE_QUALIFIER_DESCRIPTOR_LENGTH 10 + + +/* Define USBX Other Speed Descriptor structure. */ + +typedef struct UX_OTHER_SPEED_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG wTotalLength; + ULONG bNumInterfaces; + ULONG bConfigurationValue; + ULONG iConfiguration; + ULONG bmAttributes; + ULONG MaxPower; +} UX_OTHER_SPEED_DESCRIPTOR; + +#define UX_OTHER_SPEED_DESCRIPTOR_ENTRIES 8 +#define UX_OTHER_SPEED_DESCRIPTOR_LENGTH 9 + +/* Define USBX OTG Descriptor structure. */ + +typedef struct UX_OTG_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bmAttributes; + ULONG bcdOTG; +} UX_OTG_DESCRIPTOR; + +#define UX_OTG_DESCRIPTOR_ENTRIES 4 +#define UX_OTG_DESCRIPTOR_LENGTH 5 + +/* Define USBX Interface Association Descriptor structure. */ + +typedef struct UX_INTERFACE_ASSOCIATION_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bFirstInterface; + ULONG bInterfaceCount; + ULONG bFunctionClass; + ULONG bFunctionSubClass; + ULONG bFunctionProtocol; + ULONG iFunction; + +} UX_INTERFACE_ASSOCIATION_DESCRIPTOR; + +#define UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ENTRIES 8 +#define UX_INTERFACE_ASSOCIATION_DESCRIPTOR_LENGTH 8 + + +/* Define USBX Device Container structure. */ + +typedef struct UX_DEVICE_STRUCT +{ + + ULONG ux_device_handle; + ULONG ux_device_type; + ULONG ux_device_state; + ULONG ux_device_address; + ULONG ux_device_speed; + ULONG ux_device_port_location; + ULONG ux_device_max_power; + ULONG ux_device_power_source; + UINT ux_device_current_configuration; + TX_SEMAPHORE ux_device_protection_semaphore; + struct UX_DEVICE_STRUCT + *ux_device_parent; + struct UX_HOST_CLASS_STRUCT + *ux_device_class; + VOID *ux_device_class_instance; + struct UX_HCD_STRUCT + *ux_device_hcd; + struct UX_CONFIGURATION_STRUCT + *ux_device_first_configuration; + struct UX_DEVICE_STRUCT + *ux_device_next_device; + struct UX_DEVICE_DESCRIPTOR_STRUCT + ux_device_descriptor; + struct UX_ENDPOINT_STRUCT + ux_device_control_endpoint; + struct UX_HUB_TT_STRUCT + ux_device_hub_tt[UX_MAX_TT]; +} UX_DEVICE; + + +/* Define USBX Configuration Descriptor structure. */ + +typedef struct UX_CONFIGURATION_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG wTotalLength; + ULONG bNumInterfaces; + ULONG bConfigurationValue; + ULONG iConfiguration; + ULONG bmAttributes; + ULONG MaxPower; +} UX_CONFIGURATION_DESCRIPTOR; + +#define UX_CONFIGURATION_DESCRIPTOR_ENTRIES 8 +#define UX_CONFIGURATION_DESCRIPTOR_LENGTH 9 + + +/* Define USBX Configuration Container structure. */ + +typedef struct UX_CONFIGURATION_STRUCT +{ + + ULONG ux_configuration_handle; + ULONG ux_configuration_state; + ULONG ux_configuration_otg_capabilities; + struct UX_CONFIGURATION_DESCRIPTOR_STRUCT + ux_configuration_descriptor; + struct UX_INTERFACE_STRUCT + *ux_configuration_first_interface; + struct UX_CONFIGURATION_STRUCT + *ux_configuration_next_configuration; + struct UX_DEVICE_STRUCT + *ux_configuration_device; + ULONG ux_configuration_iad_class; + ULONG ux_configuration_iad_subclass; + ULONG ux_configuration_iad_protocol; +} UX_CONFIGURATION; + + +/* Define USBX Interface Descriptor structure. */ + +typedef struct UX_INTERFACE_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bInterfaceNumber; + ULONG bAlternateSetting; + ULONG bNumEndpoints; + ULONG bInterfaceClass; + ULONG bInterfaceSubClass; + ULONG bInterfaceProtocol; + ULONG iInterface; +} UX_INTERFACE_DESCRIPTOR; + +#define UX_INTERFACE_DESCRIPTOR_ENTRIES 9 +#define UX_INTERFACE_DESCRIPTOR_LENGTH 9 + + +/* Define USBX Interface Container structure. */ + +typedef struct UX_INTERFACE_STRUCT +{ + + ULONG ux_interface_handle; + ULONG ux_interface_state; + UINT ux_interface_current_alternate_setting; + struct UX_INTERFACE_DESCRIPTOR_STRUCT + ux_interface_descriptor; + struct UX_HOST_CLASS_STRUCT + *ux_interface_class; + VOID *ux_interface_class_instance; + struct UX_ENDPOINT_STRUCT + *ux_interface_first_endpoint; + struct UX_INTERFACE_STRUCT + *ux_interface_next_interface; + struct UX_CONFIGURATION_STRUCT + *ux_interface_configuration; + ULONG ux_interface_iad_class; + ULONG ux_interface_iad_subclass; + ULONG ux_interface_iad_protocol; + +} UX_INTERFACE; + + +/* Define USBX String Descriptor structure. */ + +typedef struct UX_STRING_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bString[1]; +} UX_STRING_DESCRIPTOR; + +#define UX_STRING_DESCRIPTOR_ENTRIES 3 +#define UX_STRING_DESCRIPTOR_LENGTH 4 + + +/* Define USBX DFU functional descriptor. */ + +typedef struct UX_DFU_FUNCTIONAL_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bmAttributes; + ULONG wDetachTimeOut; + ULONG wTransferSize; + ULONG bcdDFUVersion; +} UX_DFU_FUNCTIONAL_DESCRIPTOR; + +#define UX_DFU_FUNCTIONAL_DESCRIPTOR_ENTRIES 6 +#define UX_DFU_FUNCTIONAL_DESCRIPTOR_LENGTH 9 + +/* Define USBX Host Controller structure. */ + +typedef struct UX_HCD_STRUCT +{ + + UCHAR ux_hcd_name[UX_MAX_HCD_NAME_LENGTH + 1]; /* "+1" for string null-terminator */ + UCHAR ux_hcd_address[16]; + UINT ux_hcd_status; + UINT ux_hcd_controller_type; + UINT ux_hcd_otg_capabilities; + UINT ux_hcd_irq; + UINT ux_hcd_nb_root_hubs; + UINT ux_hcd_root_hub_signal[16]; + UINT ux_hcd_nb_devices; + UINT ux_hcd_power_switch; + UINT ux_hcd_thread_signal; + ULONG ux_hcd_rh_device_connection; + ULONG ux_hcd_io; + ULONG ux_hcd_available_bandwidth; + ULONG ux_hcd_maximum_transfer_request_size; + ULONG ux_hcd_version; + UINT (*ux_hcd_entry_function) (struct UX_HCD_STRUCT *, UINT, VOID *); + void *ux_hcd_controller_hardware; +} UX_HCD; + + +/* Define USBX Device Transfer Request structure. */ + +typedef struct UX_SLAVE_TRANSFER_STRUCT +{ + + ULONG ux_slave_transfer_request_status; + ULONG ux_slave_transfer_request_type; + struct UX_SLAVE_ENDPOINT_STRUCT + *ux_slave_transfer_request_endpoint; + UCHAR *ux_slave_transfer_request_data_pointer; + UCHAR *ux_slave_transfer_request_current_data_pointer; + ULONG ux_slave_transfer_request_requested_length; + ULONG ux_slave_transfer_request_actual_length; + ULONG ux_slave_transfer_request_in_transfer_length; + ULONG ux_slave_transfer_request_completion_code; + ULONG ux_slave_transfer_request_phase; + VOID (*ux_slave_transfer_request_completion_function) (struct UX_SLAVE_TRANSFER_STRUCT *); + TX_SEMAPHORE ux_slave_transfer_request_semaphore; + ULONG ux_slave_transfer_request_timeout; + ULONG ux_slave_transfer_request_force_zlp; + UCHAR ux_slave_transfer_request_setup[UX_SETUP_SIZE]; + ULONG ux_slave_transfer_request_status_phase_ignore; +} UX_SLAVE_TRANSFER; + + +/* Define USBX Device Controller Endpoint structure. */ + +typedef struct UX_SLAVE_ENDPOINT_STRUCT +{ + + ULONG ux_slave_endpoint_status; + ULONG ux_slave_endpoint_state; + void *ux_slave_endpoint_ed; + struct UX_ENDPOINT_DESCRIPTOR_STRUCT + ux_slave_endpoint_descriptor; + struct UX_SLAVE_ENDPOINT_STRUCT + *ux_slave_endpoint_next_endpoint; + struct UX_SLAVE_INTERFACE_STRUCT + *ux_slave_endpoint_interface; + struct UX_SLAVE_DEVICE_STRUCT + *ux_slave_endpoint_device; + struct UX_SLAVE_TRANSFER_STRUCT + ux_slave_endpoint_transfer_request; +} UX_SLAVE_ENDPOINT; + + +/* Define USBX Device Controller Interface structure. */ + +typedef struct UX_SLAVE_INTERFACE_STRUCT +{ + ULONG ux_slave_interface_status; + struct UX_SLAVE_CLASS_STRUCT + *ux_slave_interface_class; + VOID *ux_slave_interface_class_instance; + + struct UX_INTERFACE_DESCRIPTOR_STRUCT + ux_slave_interface_descriptor; + struct UX_SLAVE_INTERFACE_STRUCT + *ux_slave_interface_next_interface; + struct UX_SLAVE_ENDPOINT_STRUCT + *ux_slave_interface_first_endpoint; +} UX_SLAVE_INTERFACE; + + +/* Define USBX Device Controller structure. */ + +typedef struct UX_SLAVE_DEVICE_STRUCT +{ + + ULONG ux_slave_device_state; + struct UX_DEVICE_DESCRIPTOR_STRUCT + ux_slave_device_descriptor; + struct UX_SLAVE_ENDPOINT_STRUCT + ux_slave_device_control_endpoint; + ULONG ux_slave_device_configuration_selected; + struct UX_CONFIGURATION_DESCRIPTOR_STRUCT + ux_slave_device_configuration_descriptor; + struct UX_SLAVE_INTERFACE_STRUCT + *ux_slave_device_first_interface; + struct UX_SLAVE_INTERFACE_STRUCT + *ux_slave_device_interfaces_pool; + ULONG ux_slave_device_interfaces_pool_number; + struct UX_SLAVE_ENDPOINT_STRUCT + *ux_slave_device_endpoints_pool; + ULONG ux_slave_device_endpoints_pool_number; + ULONG ux_slave_device_power_state; + +} UX_SLAVE_DEVICE; + + +/* Define USBX Device Controller structure. */ + +typedef struct UX_SLAVE_DCD_STRUCT +{ + + UCHAR ux_slave_dcd_name[32]; + UINT ux_slave_dcd_status; + UINT ux_slave_dcd_controller_type; + UINT ux_slave_dcd_otg_capabilities; + UINT ux_slave_dcd_irq; + ULONG ux_slave_dcd_io; + ULONG ux_slave_dcd_device_address; + UINT (*ux_slave_dcd_function) (struct UX_SLAVE_DCD_STRUCT *,UINT, VOID *); + void *ux_slave_dcd_controller_hardware; +} UX_SLAVE_DCD; + +/* Define USBX Device Class Command container structure. */ + +typedef struct UX_SLAVE_CLASS_COMMAND_STRUCT +{ + + UINT ux_slave_class_command_request; + VOID *ux_slave_class_command_container; + VOID *ux_slave_class_command_interface; + UINT ux_slave_class_command_pid; + UINT ux_slave_class_command_vid; + UINT ux_slave_class_command_class; + UINT ux_slave_class_command_subclass; + UINT ux_slave_class_command_protocol; + struct UX_SLAVE_CLASS_STRUCT + *ux_slave_class_command_class_ptr; + VOID *ux_slave_class_command_parameter; + VOID *ux_slave_class_command_interface_number; + +} UX_SLAVE_CLASS_COMMAND; + + +/* Define USBX Device Class container structure. */ + +typedef struct UX_SLAVE_CLASS_STRUCT +{ + + UCHAR ux_slave_class_name[UX_MAX_CLASS_NAME_LENGTH + 1]; /* "+1" for string null-terminator */ + UINT ux_slave_class_status; + UINT (*ux_slave_class_entry_function) (struct UX_SLAVE_CLASS_COMMAND_STRUCT *) ; + VOID *ux_slave_class_instance; + VOID *ux_slave_class_client; + TX_THREAD ux_slave_class_thread; + VOID *ux_slave_class_thread_stack; + VOID *ux_slave_class_interface_parameter; + ULONG ux_slave_class_interface_number; + ULONG ux_slave_class_configuration_number; + struct UX_SLAVE_INTERFACE_STRUCT + *ux_slave_class_interface; + +} UX_SLAVE_CLASS; + +/* Define USBX Memory Management structure. */ + +typedef struct UX_MEMORY_BLOCK_STRUCT +{ + + ULONG ux_memory_block_size; + ULONG ux_memory_block_status; + struct UX_MEMORY_BLOCK_STRUCT + *ux_memory_block_next; + struct UX_MEMORY_BLOCK_STRUCT + *ux_memory_block_previous; +} UX_MEMORY_BLOCK; + + +typedef struct UX_SYSTEM_STRUCT +{ + + UX_MEMORY_BLOCK *ux_system_regular_memory_pool_start; + ULONG ux_system_regular_memory_pool_size; + ULONG ux_system_regular_memory_pool_free; + UX_MEMORY_BLOCK *ux_system_cache_safe_memory_pool_start; + ULONG ux_system_cache_safe_memory_pool_size; + ULONG ux_system_cache_safe_memory_pool_free; + UINT ux_system_thread_lowest_priority; + TX_MUTEX ux_system_mutex; + ULONG ux_system_debug_code; + ULONG ux_system_debug_count; + UINT ux_system_last_error; + UINT ux_system_error_count; + UCHAR *ux_system_debug_log_buffer; + UCHAR *ux_system_debug_log_head; + UCHAR *ux_system_debug_log_tail; + ULONG ux_system_debug_log_size; + VOID (*ux_system_debug_callback_function) (UCHAR *debug_message, ULONG debug_value) ; + VOID (*ux_system_error_callback_function) (UINT system_level, UINT system_context, UINT error_code) ; +} UX_SYSTEM; + + +/* Define USBX System Host Data structure. */ + +typedef struct UX_SYSTEM_HOST_STRUCT +{ + + UINT ux_system_host_max_class; + UINT ux_system_host_registered_class; + UX_HOST_CLASS *ux_system_host_class_array; + UINT ux_system_host_max_hcd; + UX_HCD *ux_system_host_hcd_array; + UINT ux_system_host_registered_hcd; + UX_DEVICE *ux_system_host_device_array; + ULONG ux_system_host_max_devices; + ULONG ux_system_host_max_ed; + ULONG ux_system_host_max_td; + ULONG ux_system_host_max_iso_td; + UINT ux_system_host_rhsc_hcd; + UCHAR *ux_system_host_enum_thread_stack; + TX_THREAD ux_system_host_enum_thread; + TX_SEMAPHORE ux_system_host_enum_semaphore; + VOID (*ux_system_host_enum_hub_function) (VOID); + UCHAR *ux_system_host_hcd_thread_stack; + TX_THREAD ux_system_host_hcd_thread; + UCHAR *ux_system_host_hnp_polling_thread_stack; + TX_THREAD ux_system_host_hnp_polling_thread; + TX_SEMAPHORE ux_system_host_hcd_semaphore; + UINT (*ux_system_host_change_function) (ULONG, UX_HOST_CLASS *, VOID *); +} UX_SYSTEM_HOST; + + +typedef struct UX_SYSTEM_SLAVE_STRUCT +{ + + UX_SLAVE_DCD ux_system_slave_dcd; + UX_SLAVE_DEVICE ux_system_slave_device; + UCHAR *ux_system_slave_device_framework; + ULONG ux_system_slave_device_framework_length; + UCHAR *ux_system_slave_device_framework_full_speed; + ULONG ux_system_slave_device_framework_length_full_speed; + UCHAR *ux_system_slave_device_framework_high_speed; + ULONG ux_system_slave_device_framework_length_high_speed; + UCHAR *ux_system_slave_string_framework; + ULONG ux_system_slave_string_framework_length; + UCHAR *ux_system_slave_language_id_framework; + ULONG ux_system_slave_language_id_framework_length; + UCHAR *ux_system_slave_dfu_framework; + ULONG ux_system_slave_dfu_framework_length; + UINT ux_system_slave_max_class; + UINT ux_system_slave_registered_class; + UX_SLAVE_CLASS *ux_system_slave_class_array; + UX_SLAVE_CLASS *ux_system_slave_interface_class_array[UX_MAX_SLAVE_INTERFACES]; + ULONG ux_system_slave_speed; + ULONG ux_system_slave_power_state; + ULONG ux_system_slave_remote_wakeup_capability; + ULONG ux_system_slave_remote_wakeup_enabled; + ULONG ux_system_slave_device_dfu_capabilities; + ULONG ux_system_slave_device_dfu_detach_timeout; + ULONG ux_system_slave_device_dfu_transfer_size; + ULONG ux_system_slave_device_dfu_state_machine; + ULONG ux_system_slave_device_dfu_mode; + UINT (*ux_system_slave_change_function) (ULONG); + ULONG ux_system_slave_device_vendor_request; + UINT (*ux_system_slave_device_vendor_request_function) (ULONG, ULONG, ULONG, ULONG, UCHAR *, ULONG *); + +} UX_SYSTEM_SLAVE; + +typedef struct UX_SYSTEM_OTG_STRUCT +{ + + TX_THREAD ux_system_otg_thread; + UCHAR *ux_system_otg_thread_stack; + TX_SEMAPHORE ux_system_otg_semaphore; + UINT (*ux_system_otg_function) (ULONG); + ULONG ux_system_otg_mode; + ULONG ux_system_otg_io; + ULONG ux_system_otg_vbus_state; + ULONG ux_system_otg_change_mode_event; + ULONG ux_system_otg_change_vbus_event; + ULONG ux_system_otg_slave_role_swap_flag; + ULONG ux_system_otg_slave_set_feature_flag; + ULONG ux_system_otg_device_type; + VOID (*ux_system_otg_vbus_function) (ULONG); + VOID (*ux_system_otg_change_mode_callback) (ULONG); +} UX_SYSTEM_OTG; + +/* Define Data Pump Class instance structure. */ + + +typedef struct UX_HOST_CLASS_DPUMP_STRUCT +{ + + struct UX_HOST_CLASS_DPUMP_STRUCT + *ux_host_class_dpump_next_instance; + UX_HOST_CLASS *ux_host_class_dpump_class; + UX_DEVICE *ux_host_class_dpump_device; + UX_INTERFACE *ux_host_class_dpump_interface; + UX_ENDPOINT *ux_host_class_dpump_bulk_out_endpoint; + UX_ENDPOINT *ux_host_class_dpump_bulk_in_endpoint; + UX_ENDPOINT *ux_host_class_dpump_interrupt_endpoint; + UINT ux_host_class_dpump_state; + TX_SEMAPHORE ux_host_class_dpump_semaphore; +} UX_HOST_CLASS_DPUMP; + + +/* Define the system API mappings based on the error checking + selected by the user. Note: this section is only applicable to + application source code, hence the conditional that turns off this + stuff when the include file is processed by the ThreadX source. */ + +#ifndef UX_SOURCE_CODE + + +/* Define USBX Services. */ + +#define ux_system_initialize _ux_system_initialize +#define ux_system_uninitialize _ux_system_uninitialize + +#define ux_host_class_hub_entry _ux_host_class_hub_entry + +#define ux_host_class_storage_entry _ux_host_class_storage_entry + +#define ux_host_stack_class_get _ux_host_stack_class_get +#define ux_host_stack_class_instance_create _ux_host_stack_class_instance_create +#define ux_host_stack_class_instance_destroy _ux_host_stack_class_instance_destroy +#define ux_host_stack_class_instance_get _ux_host_stack_class_instance_get +#define ux_host_stack_class_register _ux_host_stack_class_register +#define ux_host_stack_configuration_interface_get _ux_host_stack_configuration_interface_get +#define ux_host_stack_device_configuration_get _ux_host_stack_device_configuration_get +#define ux_host_stack_device_configuration_select _ux_host_stack_device_configuration_select +#define ux_host_stack_device_get _ux_host_stack_device_get +#define ux_host_stack_endpoint_transfer_abort _ux_host_stack_endpoint_transfer_abort +#define ux_host_stack_hcd_register _ux_host_stack_hcd_register +#define ux_host_stack_initialize _ux_host_stack_initialize +#define ux_host_stack_interface_endpoint_get _ux_host_stack_interface_endpoint_get +#define ux_host_stack_interface_setting_select _ux_host_stack_interface_setting_select +#define ux_host_stack_transfer_request _ux_host_stack_transfer_request +#define ux_host_stack_transfer_request_abort _ux_host_stack_transfer_request_abort +#define ux_host_stack_hnp_polling_thread_entry _ux_host_stack_hnp_polling_thread_entry +#define ux_host_stack_role_swap _ux_host_stack_role_swap +#define ux_host_stack_device_configuration_reset _ux_host_stack_device_configuration_reset + +#define ux_utility_pci_class_scan _ux_utility_pci_class_scan +#define ux_utility_pci_read _ux_utility_pci_read +#define ux_utility_pci_write _ux_utility_pci_write + +#define ux_device_stack_alternate_setting_get _ux_device_stack_alternate_setting_get +#define ux_device_stack_alternate_setting_set _ux_device_stack_alternate_setting_set +#define ux_device_stack_class_register _ux_device_stack_class_register +#define ux_device_stack_class_unregister _ux_device_stack_class_unregister +#define ux_device_stack_configuration_get _ux_device_stack_configuration_get +#define ux_device_stack_configuration_set _ux_device_stack_configuration_set +#define ux_device_stack_descriptor_send _ux_device_stack_descriptor_send +#define ux_device_stack_connect _ux_device_stack_connect +#define ux_device_stack_disconnect _ux_device_stack_disconnect +#define ux_device_stack_endpoint_stall _ux_device_stack_endpoint_stall +#define ux_device_stack_host_wakeup _ux_device_stack_host_wakeup +#define ux_device_stack_initialize _ux_device_stack_initialize +#define ux_device_stack_uninitialize _ux_device_stack_uninitialize +#define ux_device_stack_interface_delete _ux_device_stack_interface_delete +#define ux_device_stack_interface_get _ux_device_stack_interface_get +#define ux_device_stack_interface_set _ux_device_stack_interface_set +#define ux_device_stack_interface_start _ux_device_stack_interface_start +#define ux_device_stack_transfer_request _ux_device_stack_transfer_request +#define ux_device_stack_transfer_abort _ux_device_stack_transfer_abort + +#define ux_hcd_ehci_initialize _ux_hcd_ehci_initialize +#define ux_hcd_isp1161_initialize _ux_hcd_isp1161_initialize +#define ux_hcd_ohci_initialize _ux_hcd_ohci_initialize +#define ux_hcd_sim_host_initialize _ux_hcd_sim_host_initialize +#define ux_dcd_sim_slave_initialize _ux_dcd_sim_slave_initialize + +#define ux_network_driver_init _ux_network_driver_init +#endif + + +/* Define USBX API prototypes. */ + +UINT ux_system_initialize(VOID *non_cached_memory_pool_start, ULONG non_cached_memory_size, + VOID *cached_memory_pool_start, ULONG cached_memory_size); +UINT ux_system_uninitialize(VOID); + +/* Define USBX Host API prototypes. */ + +UINT ux_hcd_ehci_initialize(UX_HCD *hcd); +UINT ux_hcd_isp1161_initialize(UX_HCD *hcd); +UINT ux_hcd_ohci_initialize(UX_HCD *hcd); +UINT ux_hcd_sim_host_initialize(UX_HCD *hcd); + +UINT ux_host_stack_class_get(UCHAR *class_name, UX_HOST_CLASS **host_class); +UINT ux_host_stack_class_instance_create(UX_HOST_CLASS *host_class, VOID *class_instance); +UINT ux_host_stack_class_instance_destroy(UX_HOST_CLASS *host_class, VOID *class_instance); +UINT ux_host_stack_class_instance_get(UX_HOST_CLASS *host_class, UINT class_index, VOID **class_instance); +UINT ux_host_stack_class_register(UCHAR *class_name, UINT (*class_entry_function)(struct UX_HOST_CLASS_COMMAND_STRUCT *)); +UINT ux_host_stack_configuration_interface_get(UX_CONFIGURATION *configuration, UINT interface_index, + UINT alternate_setting_index, UX_INTERFACE **interface); +UINT ux_host_stack_device_configuration_get(UX_DEVICE *device, UINT configuration_index, UX_CONFIGURATION **configuration); +UINT ux_host_stack_device_configuration_select(UX_CONFIGURATION *configuration); +UINT ux_host_stack_device_get(ULONG device_index, UX_DEVICE **device); +UINT ux_host_stack_endpoint_transfer_abort(UX_ENDPOINT *endpoint); +UINT ux_host_stack_hcd_register(UCHAR *hcd_name, UINT (*hcd_initialize_function)(struct UX_HCD_STRUCT *), ULONG hcd_param1, ULONG hcd_param2); +UINT ux_host_stack_initialize(UINT (*ux_system_host_change_function)(ULONG, UX_HOST_CLASS *, VOID *)); +UINT ux_host_stack_interface_endpoint_get(UX_INTERFACE *interface, UINT endpoint_index, UX_ENDPOINT **endpoint); +UINT ux_host_stack_interface_setting_select(UX_INTERFACE *interface); +UINT ux_host_stack_transfer_request(UX_TRANSFER *transfer_request); +UINT ux_host_stack_transfer_request_abort(UX_TRANSFER *transfer_request); +VOID ux_host_stack_hnp_polling_thread_entry(ULONG id); +UINT ux_host_stack_role_swap(UX_DEVICE *device); +UINT ux_host_stack_device_configuration_reset(UX_DEVICE *device); + + +/* Define USBX Device API prototypes. */ + +UINT ux_dcd_at91_initialize(ULONG dcd_io); +UINT ux_dcd_isp1181_initialize(ULONG dcd_io, ULONG dcd_irq, ULONG dcd_vbus_address); +UINT ux_dcd_ml6965_initialize(ULONG dcd_io, ULONG dcd_irq, ULONG dcd_vbus_address); +UINT ux_dcd_sim_slave_initialize(VOID); + +UINT ux_device_class_storage_entry(UX_SLAVE_CLASS_COMMAND *command); +VOID ux_device_class_storage_thread(ULONG); +UINT ux_device_stack_alternate_setting_get(ULONG interface_value); +UINT ux_device_stack_alternate_setting_set(ULONG interface_value, ULONG alternate_setting_value); +UINT ux_device_stack_class_register(UCHAR *class_name, + UINT (*class_entry_function)(struct UX_SLAVE_CLASS_COMMAND_STRUCT *), + ULONG configuration_number, + ULONG interface_number, + VOID *parameter); +UINT ux_device_stack_class_unregister(UCHAR *class_name, + UINT (*class_entry_function)(struct UX_SLAVE_CLASS_COMMAND_STRUCT *)); +UINT ux_device_stack_configuration_get(VOID); +UINT ux_device_stack_configuration_set(ULONG configuration_value); +UINT ux_device_stack_descriptor_send(ULONG descriptor_type, ULONG request_index, ULONG host_length); +UINT ux_device_stack_disconnect(VOID); +UINT ux_device_stack_endpoint_stall(UX_SLAVE_ENDPOINT *endpoint); +UINT ux_device_stack_host_wakeup(VOID); +UINT ux_device_stack_initialize(UCHAR * device_framework_high_speed, ULONG device_framework_length_high_speed, + UCHAR * device_framework_full_speed, ULONG device_framework_length_full_speed, + UCHAR * string_framework, ULONG string_framework_length, + UCHAR * language_id_framework, ULONG language_id_framework_length, + UINT (*ux_system_slave_change_function)(ULONG)); +UINT ux_device_stack_uninitialize(VOID); +UINT ux_device_stack_interface_delete(UX_SLAVE_INTERFACE *interface); +UINT ux_device_stack_interface_get(UINT interface_value); +UINT ux_device_stack_interface_set(UCHAR * device_framework, ULONG device_framework_length, + ULONG alternate_setting_value); +UINT ux_device_stack_interface_start(UX_SLAVE_INTERFACE *interface); +UINT ux_device_stack_transfer_request(UX_SLAVE_TRANSFER *transfer_request, ULONG slave_length, ULONG host_length); +UINT ux_device_stack_transfer_request_abort(UX_SLAVE_TRANSFER *transfer_request, ULONG completion_code); + +/* Include USBX utility and system file. */ + +#include "ux_utility.h" +#include "ux_system.h" + + + + +/* Determine if a C++ compiler is being used. If so, complete the standard + C conditional started above. */ +#ifdef __cplusplus + } +#endif + + +#endif + + diff --git a/common/core/inc/ux_dcd_sim_slave.h b/common/core/inc/ux_dcd_sim_slave.h new file mode 100644 index 0000000..82bf23c --- /dev/null +++ b/common/core/inc/ux_dcd_sim_slave.h @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_dcd_sim_slave.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX slave simulator. It is designed to work ONLY with the USBX */ +/* host simulator. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DCD_SIM_SLAVE_H +#define UX_DCD_SIM_SLAVE_H + + +/* Define USB slave simulator major equivalences. */ + +#define UX_DCD_SIM_SLAVE_SLAVE_CONTROLLER 98 +#define UX_DCD_SIM_SLAVE_MAX_ED 16 + + +/* Define USB slave simulator error code register bits. */ + +#define UX_DCD_SIM_SLAVE_ERROR_TRANSMISSION_OK 0x00000001 +#define UX_DCD_SIM_SLAVE_ERROR_CODE_MASK 0x0000000e +#define UX_DCD_SIM_SLAVE_ERROR_CODE_SHIFT 0x00000001 +#define UX_DCD_SIM_SLAVE_ERROR_CODE_PID_ERROR 0x00000001 +#define UX_DCD_SIM_SLAVE_ERROR_CODE_PID_UNKNOWN 0x00000002 +#define UX_DCD_SIM_SLAVE_ERROR_CODE_UNEXPECTED_PACKET 0x00000003 +#define UX_DCD_SIM_SLAVE_ERROR_CODE_TOKEN_CRC 0x00000004 +#define UX_DCD_SIM_SLAVE_ERROR_CODE_DATA_CRC 0x00000005 +#define UX_DCD_SIM_SLAVE_ERROR_CODE_TIME_OUT 0x00000006 +#define UX_DCD_SIM_SLAVE_ERROR_CODE_BABBLE 0x00000007 +#define UX_DCD_SIM_SLAVE_ERROR_CODE_UNEXPECTED_EOP 0x00000008 +#define UX_DCD_SIM_SLAVE_ERROR_CODE_NAK 0x00000009 +#define UX_DCD_SIM_SLAVE_ERROR_CODE_STALLED 0x0000000a +#define UX_DCD_SIM_SLAVE_ERROR_CODE_OVERFLOW 0x0000000b +#define UX_DCD_SIM_SLAVE_ERROR_CODE_EMPTY_PACKET 0x0000000c +#define UX_DCD_SIM_SLAVE_ERROR_CODE_BIT_STUFFING 0x0000000d +#define UX_DCD_SIM_SLAVE_ERROR_CODE_SYNC_ERROR 0x0000000e +#define UX_DCD_SIM_SLAVE_ERROR_CODE_DATA_TOGGLE 0x0000000f + + +/* Define USB slave simulator physical endpoint status definition. */ + +#define UX_DCD_SIM_SLAVE_ED_STATUS_UNUSED 0 +#define UX_DCD_SIM_SLAVE_ED_STATUS_USED 1 +#define UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER 2 +#define UX_DCD_SIM_SLAVE_ED_STATUS_STALLED 4 + + +/* Define USB slave simulator physical endpoint structure. */ + +typedef struct UX_DCD_SIM_SLAVE_ED_STRUCT +{ + + ULONG ux_sim_slave_ed_status; + ULONG ux_sim_slave_ed_index; + ULONG ux_sim_slave_ed_payload_length; + ULONG ux_sim_slave_ed_ping_pong; + ULONG ux_sim_slave_ed_status_register; + ULONG ux_sim_slave_ed_configuration_value; + struct UX_SLAVE_ENDPOINT_STRUCT + *ux_sim_slave_ed_endpoint; +} UX_DCD_SIM_SLAVE_ED; + + +/* Define USB slave simulator DCD structure definition. */ + +typedef struct UX_DCD_SIM_SLAVE_STRUCT +{ + + struct UX_SLAVE_DCD_STRUCT + *ux_dcd_sim_slave_dcd_owner; + struct UX_DCD_SIM_SLAVE_ED_STRUCT + ux_dcd_sim_slave_ed[UX_DCD_SIM_SLAVE_MAX_ED]; + UINT (*ux_dcd_sim_slave_dcd_control_request_process_hub)(UX_SLAVE_TRANSFER *transfer_request); +} UX_DCD_SIM_SLAVE; + + +/* Define slave simulator function prototypes. */ + +UINT _ux_dcd_sim_slave_address_set(UX_DCD_SIM_SLAVE *dcd_sim_slave, ULONG address); +UINT _ux_dcd_sim_slave_endpoint_create(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_ENDPOINT *endpoint); +UINT _ux_dcd_sim_slave_endpoint_destroy(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_ENDPOINT *endpoint); +UINT _ux_dcd_sim_slave_endpoint_reset(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_ENDPOINT *endpoint); +UINT _ux_dcd_sim_slave_endpoint_stall(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_ENDPOINT *endpoint); +UINT _ux_dcd_sim_slave_endpoint_status(UX_DCD_SIM_SLAVE *dcd_sim_slave, ULONG endpoint_index); +UINT _ux_dcd_sim_slave_frame_number_get(UX_DCD_SIM_SLAVE *dcd_sim_slave, ULONG *frame_number); +UINT _ux_dcd_sim_slave_function(UX_SLAVE_DCD *dcd, UINT function, VOID *parameter); +UINT _ux_dcd_sim_slave_initialize(VOID); +UINT _ux_dcd_sim_slave_initialize_complete(VOID); +UINT _ux_dcd_sim_slave_state_change(UX_DCD_SIM_SLAVE *dcd_sim_slave, ULONG state); +UINT _ux_dcd_sim_slave_transfer_request(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_TRANSFER *transfer_request); +UINT _ux_dcd_sim_slave_transfer_abort(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_TRANSFER *transfer_request); + +/* Define Device Simulator Class API prototypes. */ + +#define ux_dcd_sim_slave_initialize _ux_dcd_sim_slave_initialize +#endif + diff --git a/common/core/inc/ux_device_class_dpump.h b/common/core/inc/ux_device_class_dpump.h new file mode 100644 index 0000000..cfed0b2 --- /dev/null +++ b/common/core/inc/ux_device_class_dpump.h @@ -0,0 +1,101 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_dpump.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX device dpump class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_DPUMP_H +#define UX_DEVICE_CLASS_DPUMP_H + + +/* Define Storage Class USB Class constants. */ + +#define UX_SLAVE_CLASS_DPUMP_CLASS 0x99 +#define UX_SLAVE_CLASS_DPUMP_SUBCLASS 0x99 +#define UX_SLAVE_CLASS_DPUMP_PROTOCOL 0x99 + +/* Define Data Pump Class packet equivalences. */ +#define UX_DEVICE_CLASS_DPUMP_PACKET_SIZE 128 + + +/* Define Slave DPUMP Class Calling Parameter structure */ + +typedef struct UX_SLAVE_CLASS_DPUMP_PARAMETER_STRUCT +{ + VOID (*ux_slave_class_dpump_instance_activate)(VOID *); + VOID (*ux_slave_class_dpump_instance_deactivate)(VOID *); + +} UX_SLAVE_CLASS_DPUMP_PARAMETER; + +/* Define Slave Data Pump Class structure. */ + +typedef struct UX_SLAVE_CLASS_DPUMP_STRUCT +{ + UX_SLAVE_INTERFACE *ux_slave_class_dpump_interface; + UX_SLAVE_CLASS_DPUMP_PARAMETER ux_slave_class_dpump_parameter; + UX_SLAVE_ENDPOINT *ux_slave_class_dpump_bulkin_endpoint; + UX_SLAVE_ENDPOINT *ux_slave_class_dpump_bulkout_endpoint; + ULONG ux_slave_class_dpump_alternate_setting; + + +} UX_SLAVE_CLASS_DPUMP; + +/* Define Device Data Pump Class prototypes. */ + +UINT _ux_device_class_dpump_initialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_dpump_activate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_dpump_deactivate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_dpump_entry(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_dpump_read(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_device_class_dpump_write(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_device_class_dpump_change(UX_SLAVE_CLASS_COMMAND *command); + +/* Define Device DPUMP Class API prototypes. */ + +#define ux_device_class_dpump_entry _ux_device_class_dpump_entry +#define ux_device_class_dpump_read _ux_device_class_dpump_read +#define ux_device_class_dpump_write _ux_device_class_dpump_write + +#endif diff --git a/common/core/inc/ux_device_stack.h b/common/core/inc/ux_device_stack.h new file mode 100644 index 0000000..f9ad783 --- /dev/null +++ b/common/core/inc/ux_device_stack.h @@ -0,0 +1,87 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_stack.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the equivalences for the USBX Device Stack */ +/* component. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_STACK_H +#define UX_DEVICE_STACK_H + + +/* Define USB Device Stack prototypes. */ + +UINT _ux_device_stack_alternate_setting_get(ULONG interface_value); +UINT _ux_device_stack_alternate_setting_set(ULONG interface_value, ULONG alternate_setting_value); +UINT _ux_device_stack_class_register(UCHAR *class_name, + UINT (*class_entry_function)(struct UX_SLAVE_CLASS_COMMAND_STRUCT *), + ULONG configuration_number, + ULONG interface_number, + VOID *parameter); +UINT _ux_device_stack_clear_feature(ULONG request_type, ULONG request_value, ULONG request_index); +UINT _ux_device_stack_configuration_get(VOID); +UINT _ux_device_stack_configuration_set(ULONG configuration_value); +UINT _ux_device_stack_control_request_process(UX_SLAVE_TRANSFER *transfer_request); +UINT _ux_device_stack_descriptor_send(ULONG descriptor_type, ULONG request_index, ULONG host_length); +UINT _ux_device_stack_disconnect(VOID); +UINT _ux_device_stack_endpoint_stall(UX_SLAVE_ENDPOINT *endpoint); +UINT _ux_device_stack_get_status(ULONG request_type, ULONG request_index, ULONG request_length); +UINT _ux_device_stack_host_wakeup(VOID); +UINT _ux_device_stack_initialize(UCHAR * device_framework_high_speed, ULONG device_framework_length_high_speed, + UCHAR * device_framework_full_speed, ULONG device_framework_length_full_speed, + UCHAR * string_framework, ULONG string_framework_length, + UCHAR * language_id_framework, ULONG language_id_framework_length, + UINT (*ux_system_slave_change_function)(ULONG)); +UINT _ux_device_stack_interface_delete(UX_SLAVE_INTERFACE *interface); +UINT _ux_device_stack_interface_get(UINT interface_value); +UINT _ux_device_stack_interface_set(UCHAR * device_framework, ULONG device_framework_length, + ULONG alternate_setting_value); +UINT _ux_device_stack_interface_start(UX_SLAVE_INTERFACE *interface); +UINT _ux_device_stack_set_feature(ULONG request_type, ULONG request_value, ULONG request_index); +UINT _ux_device_stack_transfer_all_request_abort(UX_SLAVE_ENDPOINT *endpoint, ULONG completion_code); +UINT _ux_device_stack_transfer_request(UX_SLAVE_TRANSFER *transfer_request, ULONG slave_length, ULONG host_length); +UINT _ux_device_stack_transfer_abort(UX_SLAVE_TRANSFER *transfer_request, ULONG completion_code); +UINT _ux_device_stack_class_unregister(UCHAR *class_name, UINT (*class_entry_function)(struct UX_SLAVE_CLASS_COMMAND_STRUCT *)); +UINT _ux_device_stack_microsoft_extension_register(ULONG vendor_request, UINT (*vendor_request_function)(ULONG, ULONG, ULONG, ULONG, UCHAR *, ULONG *)); +UINT _ux_device_stack_uninitialize(VOID); + +#endif + diff --git a/common/core/inc/ux_hcd_sim_host.h b/common/core/inc/ux_hcd_sim_host.h new file mode 100644 index 0000000..fae2c9d --- /dev/null +++ b/common/core/inc/ux_hcd_sim_host.h @@ -0,0 +1,236 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_hcd_sim_host.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX host simulator. It is designed to work ONLY with the USBX */ +/* device (slave) simulator. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HCD_SIM_HOST_H +#define UX_HCD_SIM_HOST_H + + +/* Define simulator host generic definitions. */ + +#define UX_HCD_SIM_HOST_CONTROLLER 99 +#define UX_HCD_SIM_HOST_MAX_PAYLOAD 4096 +#define UX_HCD_SIM_HOST_FRAME_DELAY 4 +#define UX_HCD_SIM_HOST_PERIODIC_ENTRY_NB 32 +#define UX_HCD_SIM_HOST_PERIODIC_ENTRY_MASK 0x1f +#define UX_HCD_SIM_HOST_AVAILABLE_BANDWIDTH 6000 + + + +/* Define simulator host completion code errors. */ + +#define UX_HCD_SIM_HOST_NO_ERROR 0x00 +#define UX_HCD_SIM_HOST_ERROR_CRC 0x01 +#define UX_HCD_SIM_HOST_ERROR_BIT_STUFFING 0x02 +#define UX_HCD_SIM_HOST_ERROR_DATA_TOGGLE 0x03 +#define UX_HCD_SIM_HOST_ERROR_STALL 0x04 +#define UX_HCD_SIM_HOST_ERROR_DEVICE_NOT_RESPONDING 0x05 +#define UX_HCD_SIM_HOST_ERROR_PID_FAILURE 0x06 +#define UX_HCD_SIM_HOST_ERROR_PID_UNEXPECTED 0x07 +#define UX_HCD_SIM_HOST_ERROR_DATA_OVERRRUN 0x08 +#define UX_HCD_SIM_HOST_ERROR_DATA_UNDERRUN 0x09 +#define UX_HCD_SIM_HOST_ERROR_BUFFER_OVERRRUN 0x0c +#define UX_HCD_SIM_HOST_ERROR_BUFFER_UNDERRUN 0x0d +#define UX_HCD_SIM_HOST_NOT_ACCESSED 0x0e +#define UX_HCD_SIM_HOST_NAK 0x0f + + +/* Define simulator host structure. */ + +typedef struct UX_HCD_SIM_HOST_STRUCT +{ + + struct UX_HCD_STRUCT + *ux_hcd_sim_host_hcd_owner; + ULONG ux_hcd_sim_host_hcor; + UINT ux_hcd_sim_host_nb_root_hubs; + struct UX_HCD_SIM_HOST_ED_STRUCT + *ux_hcd_sim_host_ed_list; + struct UX_HCD_SIM_HOST_TD_STRUCT + *ux_hcd_sim_host_td_list; + struct UX_HCD_SIM_HOST_ISO_TD_STRUCT + *ux_hcd_sim_host_iso_td_list; + struct UX_HCD_SIM_HOST_ED_STRUCT + *ux_hcd_sim_host_asynch_head_ed; + struct UX_HCD_SIM_HOST_ED_STRUCT + *ux_hcd_sim_host_asynch_current_ed; + struct UX_HCD_SIM_HOST_ED_STRUCT + *ux_hcd_sim_host_iso_head_ed; + struct UX_HCD_SIM_HOST_ED_STRUCT + *ux_hcd_sim_host_interrupt_ed_list[32]; + UINT ux_hcd_sim_host_queue_empty; + UINT ux_hcd_sim_host_periodic_scheduler_active; + UINT ux_hcd_sim_host_interruptible; + ULONG ux_hcd_sim_host_interrupt_count; + TX_TIMER ux_hcd_sim_host_timer; +} UX_HCD_SIM_HOST; + + +/* Define simulator host ED structure. */ + +typedef struct UX_HCD_SIM_HOST_ED_STRUCT +{ + + struct UX_HCD_SIM_HOST_TD_STRUCT + *ux_sim_host_ed_tail_td; + struct UX_HCD_SIM_HOST_TD_STRUCT + *ux_sim_host_ed_head_td; + struct UX_HCD_SIM_HOST_ED_STRUCT + *ux_sim_host_ed_next_ed; + struct UX_HCD_SIM_HOST_ED_STRUCT + *ux_sim_host_ed_previous_ed; + ULONG ux_sim_host_ed_status; + struct UX_ENDPOINT_STRUCT + *ux_sim_host_ed_endpoint; + ULONG ux_sim_host_ed_toggle; + ULONG ux_sim_host_ed_frame; +} UX_HCD_SIM_HOST_ED; + + +/* Define simulator host ED bitmap. */ + +#define UX_HCD_SIM_HOST_ED_STATIC 0x80000000 +#define UX_HCD_SIM_HOST_ED_SKIP 0x40000000 + + +/* Define simulator host TD structure. */ + +typedef struct UX_HCD_SIM_HOST_TD_STRUCT +{ + + UCHAR * ux_sim_host_td_buffer; + ULONG ux_sim_host_td_length; + struct UX_HCD_SIM_HOST_TD_STRUCT + *ux_sim_host_td_next_td; + struct UX_TRANSFER_STRUCT + *ux_sim_host_td_transfer_request; + struct UX_HCD_SIM_HOST_TD_STRUCT + *ux_sim_host_td_next_td_transfer_request; + struct UX_HCD_SIM_HOST_ED_STRUCT + *ux_sim_host_td_ed; + ULONG ux_sim_host_td_actual_length; + ULONG ux_sim_host_td_status; + ULONG ux_sim_host_td_direction; + ULONG ux_sim_host_td_toggle; +} UX_HCD_SIM_HOST_TD; + + +/* Define simulator host TD bitmap. */ + +#define UX_HCD_SIM_HOST_TD_SETUP_PHASE 0x00010000 +#define UX_HCD_SIM_HOST_TD_DATA_PHASE 0x00020000 +#define UX_HCD_SIM_HOST_TD_STATUS_PHASE 0x00040000 +#define UX_HCD_SIM_HOST_TD_OUT 0x00000800 +#define UX_HCD_SIM_HOST_TD_IN 0x00001000 +#define UX_HCD_SIM_HOST_TD_ACK_PENDING 0x00002000 +#define UX_HCD_SIM_HOST_TD_TOGGLE_FROM_ED 0x80000000 + + +/* Define simulator host ISOCHRONOUS TD structure. */ + +typedef struct UX_HCD_SIM_HOST_ISO_TD_STRUCT +{ + + UCHAR * ux_sim_host_iso_td_buffer; + ULONG ux_sim_host_iso_td_length; + struct UX_HCD_SIM_HOST_ISO_TD_STRUCT + *ux_sim_host_iso_td_next_td; + struct UX_TRANSFER_STRUCT + *ux_sim_host_iso_td_transfer_request; + struct UX_HCD_SIM_HOST_ISO_TD_STRUCT + *ux_sim_host_iso_td_next_td_transfer_request; + struct UX_HCD_SIM_HOST_ED_STRUCT + *ux_sim_host_iso_td_ed; + ULONG ux_sim_host_iso_td_actual_length; + ULONG ux_sim_host_iso_td_status; + ULONG ux_sim_host_iso_td_direction; +} UX_HCD_SIM_HOST_ISO_TD; + + +/* Define simulator host function prototypes. */ + +VOID _ux_hcd_sim_host_asynch_queue_process(UX_HCD_SIM_HOST *hcd_sim_host); +VOID _ux_hcd_sim_host_asynch_schedule(UX_HCD_SIM_HOST *hcd_sim_host); +UINT _ux_hcd_sim_host_asynchronous_endpoint_create(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint); +UINT _ux_hcd_sim_host_asynchronous_endpoint_destroy(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint); +UX_HCD_SIM_HOST_ED + *_ux_hcd_sim_host_ed_obtain(UX_HCD_SIM_HOST *hcd_sim_host); +VOID _ux_hcd_sim_host_ed_td_clean(UX_HCD_SIM_HOST_ED *ed); +UINT _ux_hcd_sim_host_endpoint_reset(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint); +UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter); +UINT _ux_hcd_sim_host_frame_number_get(UX_HCD_SIM_HOST *hcd_sim_host, ULONG *frame_number); +VOID _ux_hcd_sim_host_frame_number_set(UX_HCD_SIM_HOST *hcd_sim_host, ULONG frame_number); +UINT _ux_hcd_sim_host_initialize(UX_HCD *hcd); +UINT _ux_hcd_sim_host_interrupt_endpoint_create(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint); +VOID _ux_hcd_sim_host_iso_queue_process(UX_HCD_SIM_HOST *hcd_sim_host); +VOID _ux_hcd_sim_host_iso_schedule(UX_HCD_SIM_HOST *hcd_sim_host); +UINT _ux_hcd_sim_host_isochronous_endpoint_create(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint); +UX_HCD_SIM_HOST_ISO_TD + *_ux_hcd_sim_host_isochronous_td_obtain(UX_HCD_SIM_HOST *hcd_sim_host); +UX_HCD_SIM_HOST_ED + *_ux_hcd_sim_host_least_traffic_list_get(UX_HCD_SIM_HOST *hcd_sim_host); +UINT _ux_hcd_sim_host_periodic_endpoint_destroy(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint); +VOID _ux_hcd_sim_host_periodic_schedule(UX_HCD_SIM_HOST *hcd_sim_host); +UINT _ux_hcd_sim_host_periodic_tree_create(UX_HCD_SIM_HOST *hcd_sim_host); +ULONG _ux_hcd_sim_host_port_status_get(UX_HCD_SIM_HOST *hcd_sim_host, ULONG port_index); +UX_HCD_SIM_HOST_TD + *_ux_hcd_sim_host_regular_td_obtain(UX_HCD_SIM_HOST *hcd_sim_host); +UINT _ux_hcd_sim_host_request_bulk_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request); +UINT _ux_hcd_sim_host_request_control_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request); +UINT _ux_hcd_sim_host_request_interrupt_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request); +UINT _ux_hcd_sim_host_request_isochronous_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request); +UINT _ux_hcd_sim_host_request_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request); +VOID _ux_hcd_sim_host_timer_function(ULONG hcd_sim_host_addr); +UINT _ux_hcd_sim_host_transaction_schedule(UX_HCD_SIM_HOST *hcd_sim_host, UX_HCD_SIM_HOST_ED *ed); +UINT _ux_hcd_sim_host_transfer_abort(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request); +UINT _ux_hcd_sim_host_port_reset(UX_HCD_SIM_HOST *hcd_sim_host, ULONG port_index); + + +/* Define Device Simulator Class API prototypes. */ + +#define ux_hcd_sim_host_initialize _ux_hcd_sim_host_initialize +#endif + diff --git a/common/core/inc/ux_host_class_dpump.h b/common/core/inc/ux_host_class_dpump.h new file mode 100644 index 0000000..4b3907e --- /dev/null +++ b/common/core/inc/ux_host_class_dpump.h @@ -0,0 +1,89 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_dpump.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX demo data pump class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_DPUMP_H +#define UX_HOST_CLASS_DPUMP_H + + +/* Define Data Pump Class constants. */ + +#define UX_HOST_CLASS_DPUMP_CLASS_TRANSFER_TIMEOUT 300000 +#define UX_HOST_CLASS_DPUMP_CLASS 0x99 +#define UX_HOST_CLASS_DPUMP_SUBCLASS 0x99 +#define UX_HOST_CLASS_DPUMP_PROTOCOL 0x99 + +/* Define Data Pump Class packet equivalences. */ +#define UX_HOST_CLASS_DPUMP_PACKET_SIZE 128 + +/* Define Data Pump Class Ioctl functions. */ +#define UX_HOST_CLASS_DPUMP_SELECT_ALTERNATE_SETTING 1 + +/* Define Data Pump Class string constants. */ + +#define UX_HOST_CLASS_DPUMP_GENERIC_NAME "USB DPUMP" + + +/* Define Printer Class function prototypes. */ + +UINT _ux_host_class_dpump_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_dpump_configure(UX_HOST_CLASS_DPUMP *dpump); +UINT _ux_host_class_dpump_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_dpump_endpoints_get(UX_HOST_CLASS_DPUMP *dpump); +UINT _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_dpump_ioctl(UX_HOST_CLASS_DPUMP *dpump, ULONG ioctl_function, + VOID *parameter); + + +#define ux_host_class_dpump_entry _ux_host_class_dpump_entry +#define ux_host_class_dpump_read _ux_host_class_dpump_read +#define ux_host_class_dpump_write _ux_host_class_dpump_write +#define ux_host_class_dpump_ioctl _ux_host_class_dpump_ioctl + +#endif diff --git a/common/core/inc/ux_host_stack.h b/common/core/inc/ux_host_stack.h new file mode 100644 index 0000000..ec62880 --- /dev/null +++ b/common/core/inc/ux_host_stack.h @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_stack.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX Host Stack component. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_STACK_H +#define UX_HOST_STACK_H + + +/* Define Host Stack component function prototypes. */ + +VOID _ux_host_stack_bandwidth_release(UX_HCD *hcd, UX_ENDPOINT *endpoint); +VOID _ux_host_stack_bandwidth_claim(UX_HCD *hcd, UX_ENDPOINT *endpoint); +UINT _ux_host_stack_bandwidth_check(UX_HCD *hcd, UX_ENDPOINT *endpoint); +UX_HOST_CLASS * _ux_host_stack_class_call(UX_HOST_CLASS_COMMAND *class_command); +UINT _ux_host_stack_class_device_scan(UX_DEVICE *device); +UINT _ux_host_stack_class_get(UCHAR *class_name, UX_HOST_CLASS **class); +UINT _ux_host_stack_class_instance_destroy(UX_HOST_CLASS *class, VOID *class_instance); +UINT _ux_host_stack_class_instance_create(UX_HOST_CLASS *class, VOID *class_instance); +UINT _ux_host_stack_class_instance_get(UX_HOST_CLASS *class, UINT class_index, VOID **class_instance); +UINT _ux_host_stack_class_instance_verify(UCHAR *class_name, VOID *class_instance); +UINT _ux_host_stack_class_interface_scan(UX_DEVICE *device); +UINT _ux_host_stack_class_register(UCHAR *class_name, + UINT (*class_entry_function)(struct UX_HOST_CLASS_COMMAND_STRUCT *)); +UINT _ux_host_stack_configuration_descriptor_parse(UX_DEVICE *device, UX_CONFIGURATION *configuration, UINT configuration_index); +UINT _ux_host_stack_configuration_enumerate(UX_DEVICE *device); +UINT _ux_host_stack_configuration_instance_create(UX_CONFIGURATION *configuration); +VOID _ux_host_stack_configuration_instance_delete(UX_CONFIGURATION *configuration); +UINT _ux_host_stack_configuration_interface_get(UX_CONFIGURATION *configuration, + UINT interface_index, UINT alternate_setting_index, + UX_INTERFACE **interface); +UINT _ux_host_stack_configuration_set(UX_CONFIGURATION *configuration); +VOID _ux_host_stack_delay_ms(ULONG time); +UINT _ux_host_stack_device_address_set(UX_DEVICE *device); +UINT _ux_host_stack_device_configuration_get(UX_DEVICE *device, UINT configuration_index, + UX_CONFIGURATION **configuration); +UINT _ux_host_stack_device_configuration_select(UX_CONFIGURATION *configuration); +UINT _ux_host_stack_device_configuration_reset(UX_DEVICE *device); +UINT _ux_host_stack_device_descriptor_read(UX_DEVICE *device); +UINT _ux_host_stack_device_get(ULONG device_index, UX_DEVICE **device); +UINT _ux_host_stack_device_remove(UX_HCD *hcd, UX_DEVICE *parent, UINT port_index); +UINT _ux_host_stack_device_resources_free(UX_DEVICE *device); +UINT _ux_host_stack_endpoint_instance_create(UX_ENDPOINT *endpoint); +VOID _ux_host_stack_endpoint_instance_delete(UX_ENDPOINT *endpoint); +UINT _ux_host_stack_endpoint_reset(UX_ENDPOINT *endpoint); +UINT _ux_host_stack_endpoint_transfer_abort(UX_ENDPOINT *endpoint); +VOID _ux_host_stack_enum_thread_entry(ULONG input); +UINT _ux_host_stack_hcd_register(UCHAR *hcd_name, + UINT (*hcd_init_function)(struct UX_HCD_STRUCT *), ULONG hcd_param1, ULONG hcd_param2); +VOID _ux_host_stack_hcd_thread_entry(ULONG input); +UINT _ux_host_stack_hcd_transfer_request(UX_TRANSFER *transfer_request); +UINT _ux_host_stack_initialize(UINT (*ux_system_host_change_function)(ULONG, UX_HOST_CLASS *, VOID *)); +UINT _ux_host_stack_interface_endpoint_get(UX_INTERFACE *interface, UINT endpoint_index, UX_ENDPOINT **endpoint); +UINT _ux_host_stack_interface_instance_create(UX_INTERFACE *interface); +VOID _ux_host_stack_interface_instance_delete(UX_INTERFACE *interface); +UINT _ux_host_stack_interface_set(UX_INTERFACE *interface); +UINT _ux_host_stack_interface_setting_select(UX_INTERFACE *interface); +UINT _ux_host_stack_interfaces_scan(UX_CONFIGURATION *configuration, UCHAR * descriptor); +VOID _ux_host_stack_new_configuration_create(UX_DEVICE *device, UX_CONFIGURATION *configuration); +UX_DEVICE *_ux_host_stack_new_device_get(VOID); +UINT _ux_host_stack_new_device_create(UX_HCD *hcd, UX_DEVICE *device_owner, + UINT port_index, UINT device_speed, + UINT port_max_power); +UINT _ux_host_stack_new_endpoint_create(UX_INTERFACE *interface, UCHAR * interface_endpoint); +UINT _ux_host_stack_new_interface_create(UX_CONFIGURATION *configuration, UCHAR * descriptor, ULONG length); +VOID _ux_host_stack_rh_change_process(VOID); +UINT _ux_host_stack_rh_device_extraction(UX_HCD *hcd, UINT port_index); +UINT _ux_host_stack_rh_device_insertion(UX_HCD *hcd, UINT port_index); +UINT _ux_host_stack_transfer_request(UX_TRANSFER *transfer_request); +UINT _ux_host_stack_transfer_request_abort(UX_TRANSFER *transfer_request); +VOID _ux_host_stack_hnp_polling_thread_entry(ULONG id); +UINT _ux_host_stack_role_swap(UX_DEVICE *device); + +#endif + diff --git a/common/core/inc/ux_system.h b/common/core/inc/ux_system.h new file mode 100644 index 0000000..06f898b --- /dev/null +++ b/common/core/inc/ux_system.h @@ -0,0 +1,136 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** System */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_system.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX main system component. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_SYSTEM_HOST_H +#define UX_SYSTEM_HOST_H + +/* Define System component function prototypes. Note that since ux_api.h + includes this file, the APIs are only declared if this file is included + by internal code in order to prevent duplicate declarations for + applications. */ + + +#ifdef UX_SOURCE_CODE +UINT _ux_system_initialize(VOID *regular_memory_pool_start, ULONG regular_memory_size, + VOID *cache_safe_memory_pool_start, ULONG cache_safe_memory_size); +UINT _ux_system_uninitialize(VOID); +#endif + +/* Define System component external data references. */ + +extern UX_SYSTEM *_ux_system; +extern UX_SYSTEM_HOST *_ux_system_host; +extern UX_SYSTEM_SLAVE *_ux_system_slave; +extern UX_SYSTEM_OTG *_ux_system_otg; +extern UCHAR _ux_system_endpoint_descriptor_structure[]; +extern UCHAR _ux_system_device_descriptor_structure[]; +extern UCHAR _ux_system_configuration_descriptor_structure[]; +extern UCHAR _ux_system_interface_descriptor_structure[]; +extern UCHAR _ux_system_interface_association_descriptor_structure[]; +extern UCHAR _ux_system_string_descriptor_structure[]; +extern UCHAR _ux_system_dfu_functional_descriptor_structure[]; +extern UCHAR _ux_system_hub_descriptor_structure[]; +extern UCHAR _ux_system_hid_descriptor_structure[]; +extern UCHAR _ux_system_class_audio_interface_descriptor_structure[]; +extern UCHAR _ux_system_class_audio_input_terminal_descriptor_structure[]; +extern UCHAR _ux_system_class_audio_output_terminal_descriptor_structure[]; +extern UCHAR _ux_system_class_audio_feature_unit_descriptor_structure[]; +extern UCHAR _ux_system_class_audio_streaming_interface_descriptor_structure[]; +extern UCHAR _ux_system_class_audio_streaming_endpoint_descriptor_structure[]; +extern UCHAR _ux_system_class_pima_storage_structure[]; +extern UCHAR _ux_system_class_pima_object_structure[]; +extern UCHAR _ux_system_ecm_interface_descriptor_structure[]; + +extern UINT _ux_system_host_hcd_periodic_tree_entries[32]; + +extern UCHAR _ux_system_host_class_hub_name[]; +extern UCHAR _ux_system_host_class_printer_name[]; +extern UCHAR _ux_system_host_class_storage_name[]; +extern UCHAR _ux_system_host_class_hid_name[]; +extern UCHAR _ux_system_host_class_audio_name[]; +extern UCHAR _ux_system_host_class_cdc_acm_name[]; +extern UCHAR _ux_system_host_class_cdc_dlc_name[]; +extern UCHAR _ux_system_host_class_cdc_ecm_name[]; +extern UCHAR _ux_system_host_class_prolific_name[]; +extern UCHAR _ux_system_host_class_dpump_name[]; +extern UCHAR _ux_system_host_class_pima_name[]; +extern UCHAR _ux_system_host_class_asix_name[]; +extern UCHAR _ux_system_host_class_swar_name[]; +extern UCHAR _ux_system_host_class_gser_name[]; +extern UCHAR _ux_system_host_class_hid_client_remote_control_name[]; +extern UCHAR _ux_system_host_class_hid_client_mouse_name[]; +extern UCHAR _ux_system_host_class_hid_client_keyboard_name[]; + +extern UCHAR _ux_system_host_hcd_ohci_name[]; +extern UCHAR _ux_system_host_hcd_ehci_name[]; +extern UCHAR _ux_system_host_hcd_isp1161_name[]; +extern UCHAR _ux_system_host_hcd_isp1362_name[]; +extern UCHAR _ux_system_host_hcd_sh2_name[]; +extern UCHAR _ux_system_host_hcd_rx_name[]; +extern UCHAR _ux_system_host_hcd_pic32_name[]; +extern UCHAR _ux_system_host_hcd_stm32_name[]; +extern UCHAR _ux_system_host_hcd_musb_name[]; +extern UCHAR _ux_system_host_hcd_atm7_name[]; +extern UCHAR _ux_system_host_hcd_simulator_name[]; + +extern UCHAR _ux_system_slave_class_storage_name[]; +extern UCHAR _ux_system_slave_class_storage_vendor_id[]; +extern UCHAR _ux_system_slave_class_storage_product_id[]; +extern UCHAR _ux_system_slave_class_storage_product_rev[]; +extern UCHAR _ux_system_slave_class_storage_product_serial[]; +extern UCHAR _ux_system_slave_class_audio_name[]; +extern UCHAR _ux_system_slave_class_cdc_acm_name[]; +extern UCHAR _ux_system_slave_class_dpump_name[]; +extern UCHAR _ux_system_slave_class_pima_name[]; +extern UCHAR _ux_system_slave_class_hid_name[]; +extern UCHAR _ux_system_slave_class_rndis_name[]; +extern UCHAR _ux_system_slave_class_cdc_ecm_name[]; +extern UCHAR _ux_system_slave_class_dfu_name[]; + + + +#endif + diff --git a/common/core/inc/ux_user.h b/common/core/inc/ux_user.h new file mode 100644 index 0000000..b7bb606 --- /dev/null +++ b/common/core/inc/ux_user.h @@ -0,0 +1,314 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** User Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* ux_user.h PORTABLE C */ +/* 6.0 */ +/* */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains user defines for configuring USBX in specific */ +/* ways. This file will have an effect only if the application and */ +/* USBX library are built with UX_INCLUDE_USER_DEFINE_FILE defined. */ +/* Note that all the defines in this file may also be made on the */ +/* command line when building USBX library and application objects. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_USER_H +#define UX_USER_H + + +/* Define various build options for the USBX port. The application should either make changes + here by commenting or un-commenting the conditional compilation defined OR supply the defines + though the compiler's equivalent of the -D option. */ +/* #define UX_THREAD_STACK_SIZE (2 * 1024) */ + +/* Define USBX Host Enum Thread Stack Size. The default is to use UX_THREAD_STACK_SIZE */ +/* +#define UX_HOST_ENUM_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE +*/ + + +/* Define USBX Host Thread Stack Size. The default is to use UX_THREAD_STACK_SIZE */ +/* +#define UX_HOST_HCD_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE +*/ + +/* Define USBX Host HNP Polling Thread Stack Size. The default is to use UX_THREAD_STACK_SIZE */ +/* +#define UX_HOST_HNP_POLLING_THREAD_STACK UX_THREAD_STACK_SIZE +*/ + +/* Override various options with default values already assigned in ux_api.h or ux_port.h. Please + also refer to ux_port.h for descriptions on each of these options. */ + +/* Defined, this value represents how many ticks per seconds for a specific hardware platform. + The default is 1000 indicating 1 tick per millisecond. */ + +/* #define UX_PERIODIC_RATE 1000 +*/ +#define UX_PERIODIC_RATE (TX_TIMER_TICKS_PER_SECOND) + +/* Defined, this value is the maximum number of classes that can be loaded by USBX. This value + represents the class container and not the number of instances of a class. For instance, if a + particular implementation of USBX needs the hub class, the printer class, and the storage + class, then the UX_MAX_CLASSES value can be set to 3 regardless of the number of devices + that belong to these classes. */ + +/* #define UX_MAX_CLASSES 3 +*/ + + +/* Defined, this value is the maximum number of classes in the device stack that can be loaded by + USBX. */ + +/* #define UX_MAX_SLAVE_CLASS_DRIVER 1 +*/ + +/* Defined, this value is the maximum number of interfaces in the device framework. */ + +/* #define UX_MAX_SLAVE_INTERFACES 16 +*/ + +/* Defined, this value represents the number of different host controllers available in the system. + For USB 1.1 support, this value will usually be 1. For USB 2.0 support, this value can be more + than 1. This value represents the number of concurrent host controllers running at the same time. + If for instance there are two instances of OHCI running, or one EHCI and one OHCI controller + running, the UX_MAX_HCD should be set to 2. */ + +/* #define UX_MAX_HCD 1 +*/ + + +/* Defined, this value represents the maximum number of devices that can be attached to the USB. + Normally, the theoretical maximum number on a single USB is 127 devices. This value can be + scaled down to conserve memory. Note that this value represents the total number of devices + regardless of the number of USB buses in the system. */ + +/* #define UX_MAX_DEVICES 127 +*/ + + +/* Defined, this value represents the current number of SCSI logical units represented in the device + storage class driver. */ + +/* #define UX_MAX_SLAVE_LUN 1 +*/ + + +/* Defined, this value represents the maximum number of SCSI logical units represented in the + host storage class driver. */ + +/* #define UX_MAX_HOST_LUN 1 +*/ + + +/* Defined, this value represents the maximum number of bytes received on a control endpoint in + the device stack. The default is 256 bytes but can be reduced in memory constraint environments. */ + +/* #define UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH 256 +*/ + + +/* Defined, this value represents the maximum number of bytes that can be received or transmitted + on any endpoint. This value cannot be less than the maximum packet size of any endpoint. The default + is 4096 bytes but can be reduced in memory constraint environments. For cd-rom support in the storage + class, this value cannot be less than 2048. */ + +#define UX_SLAVE_REQUEST_DATA_MAX_LENGTH (1024 * 2) + + +/* Defined, this value includes code to handle storage Multi-Media Commands (MMC). E.g., DVD-ROM. +*/ + +/* #define UX_SLAVE_CLASS_STORAGE_INCLUDE_MMC */ + + +/* Defined, this value represents the maximum number of bytes that a storage payload can send/receive. + The default is 8K bytes but can be reduced in memory constraint environments. */ +#define UX_HOST_CLASS_STORAGE_MEMORY_BUFFER_SIZE (1024 * 8) + +/* Define USBX Mass Storage Thread Stack Size. The default is to use UX_THREAD_STACK_SIZE. */ + +/* #define UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE + */ + +/* Defined, this value represents the maximum number of Ed, regular TDs and Isochronous TDs. These values + depend on the type of host controller and can be reduced in memory constraint environments. */ + +#define UX_MAX_ED 80 +#define UX_MAX_TD 128 +#define UX_MAX_ISO_TD 1 + +/* Defined, this value represents the maximum size of the HID decompressed buffer. This cannot be determined + in advance so we allocate a big block, usually 4K but for simple HID devices like keyboard and mouse + it can be reduced a lot. */ + +#define UX_HOST_CLASS_HID_DECOMPRESSION_BUFFER 4096 + +/* Defined, this value represents the maximum number of HID usages for a HID device. + Default is 2048 but for simple HID devices like keyboard and mouse it can be reduced a lot. */ + +#define UX_HOST_CLASS_HID_USAGES 2048 + + +/* By default, each key in each HID report from the device is reported by ux_host_class_hid_keyboard_key_get + (a HID report from the device is received whenever there is a change in a key state i.e. when a key is pressed + or released. The report contains every key that is down). There are limitations to this method such as not being + able to determine when a key has been released. + + Defined, this value causes ux_host_class_hid_keyboard_key_get to only report key changes i.e. key presses + and key releases. */ + +/* #define UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE */ + +/* Works when UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE is defined. + + Defined, this value causes ux_host_class_hid_keyboard_key_get to only report key pressed/down changes; + key released/up changes are not reported. + */ + +/* #define UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_KEY_DOWN_ONLY */ + +/* Works when UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE is defined. + + Defined, this value causes ux_host_class_hid_keyboard_key_get to report lock key (CapsLock/NumLock/ScrollLock) changes. + */ + +/* #define UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_LOCK_KEYS */ + +/* Works when UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE is defined. + + Defined, this value causes ux_host_class_hid_keyboard_key_get to report modifier key (Ctrl/Alt/Shift/GUI) changes. + */ + +/* #define UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_MODIFIER_KEYS */ + + +/* Defined, this value represents the maximum number of media for the host storage class. + Default is 8 but for memory contrained resource systems this can ne reduced to 1. */ + +#define UX_HOST_CLASS_STORAGE_MAX_MEDIA 2 + +/* Defined, this value includes code to handle storage devices that use the CB + or CBI protocol (such as floppy disks). It is off by default because these + protocols are obsolete, being superseded by the Bulk Only Transport (BOT) protocol + which virtually all modern storage devices use. +*/ + +/* #define UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT */ + +/* Defined, this value forces the memory allocation scheme to enforce alignement + of memory with the UX_SAFE_ALIGN field. +*/ + +/* #define UX_ENFORCE_SAFE_ALIGNMENT */ + +/* Defined, this value represents the number of packets in the CDC_ECM device class. + The default is 16. +*/ + +#define UX_DEVICE_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES 4 + +/* Defined, this value represents the number of packets in the CDC_ECM host class. + The default is 16. +*/ + +/* #define UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES 16 */ + +/* Defined, this value represents the number of milliseconds to wait for packet + allocation until invoking the application's error callback and retrying. + The default is 1000 milliseconds. +*/ + +/* #define UX_HOST_CLASS_CDC_ECM_PACKET_POOL_WAIT 10 */ + +/* Defined, this value represents the number of milliseconds to wait for packet + allocation until invoking the application's error callback and retrying. +*/ + +/* #define UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT 10 */ + +/* Defined, this value represents the the maximum length of HID reports on the + device. + */ + +/* #define UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH 64 */ + +/* Defined, this value represents the the maximum number of HID events/reports + that can be queued at once. + */ + +/* #define UX_DEVICE_CLASS_HID_MAX_EVENTS_QUEUE 8 */ + +/* Defined, this value will only enable the host side of usbx. */ +/* #define UX_HOST_SIDE_ONLY */ + +/* Defined, this value will only enable the device side of usbx. */ +/* #define UX_DEVICE_SIDE_ONLY */ + +/* Defined, this value will include the OTG polling thread. OTG can only be active if both host/device are present. +*/ + +#ifndef UX_HOST_SIDE_ONLY +#ifndef UX_DEVICE_SIDE_ONLY + +/* #define UX_OTG_SUPPORT */ + +#endif +#endif + +/* Defined, this value represents the maximum size of single tansfers for the SCSI data phase. +*/ + +#define UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE (1024 * 1) + +/* Defined, this value represents the size of the log pool. +*/ +#define UX_DEBUG_LOG_SIZE (1024 * 16) + + +/* DEBUG includes and macros for a specific platform go here. */ +#ifdef UX_INCLUDE_USER_DEFINE_BSP +#include "usb_bsp.h" +#include "usbh_hcs.h" +#include "usbh_stdreq.h" +#include "usbh_core.h" +#endif + +#endif + diff --git a/common/core/inc/ux_utility.h b/common/core/inc/ux_utility.h new file mode 100644 index 0000000..3f2b6e4 --- /dev/null +++ b/common/core/inc/ux_utility.h @@ -0,0 +1,234 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_utility.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX components that utilize utility functions. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_UTILITY_H +#define UX_UTILITY_H + + +/* Define Utility component function prototypes. */ + +VOID _ux_utility_descriptor_parse(UCHAR * raw_descriptor, UCHAR * descriptor_structure, + UINT descriptor_entries, UCHAR * descriptor); +VOID _ux_utility_descriptor_pack(UCHAR * descriptor, UCHAR * descriptor_structure, + UINT descriptor_entries, UCHAR * raw_descriptor); +ULONG _ux_utility_long_get(UCHAR * address); +VOID _ux_utility_long_put(UCHAR * address, ULONG value); +VOID _ux_utility_long_put_big_endian(UCHAR * address, ULONG value); +ULONG _ux_utility_long_get_big_endian(UCHAR * address); +VOID *_ux_utility_memory_allocate(ULONG memory_alignment,ULONG memory_cache_flag, ULONG memory_size_requested); +UINT _ux_utility_memory_compare(VOID *memory_source, VOID *memory_destination, ULONG length); +VOID _ux_utility_memory_copy(VOID *memory_destination, VOID *memory_source, ULONG length); +VOID _ux_utility_memory_free(VOID *memory); +ULONG _ux_utility_string_length_get(UCHAR *string); +UINT _ux_utility_string_length_check(UCHAR *input_string, UINT *string_length_ptr, UINT max_string_length); +UX_MEMORY_BLOCK *_ux_utility_memory_free_block_best_get(ULONG memory_cache_flag, ULONG memory_size_requested); +VOID _ux_utility_memory_set(VOID *destination, UCHAR value, ULONG length); +UINT _ux_utility_mutex_create(TX_MUTEX *mutex, CHAR *mutex_name); +UINT _ux_utility_mutex_delete(TX_MUTEX *mutex); +VOID _ux_utility_mutex_off(TX_MUTEX *mutex); +VOID _ux_utility_mutex_on(TX_MUTEX *mutex); +ULONG _ux_utility_pci_class_scan(ULONG pci_class, ULONG bus_number, ULONG device_number, + ULONG function_number, ULONG *current_bus_number, + ULONG *current_device_number, ULONG *current_function_number); +ULONG _ux_utility_pci_read(ULONG bus_number, ULONG device_number, ULONG function_number, + ULONG offset, UINT read_size); +VOID _ux_utility_pci_write(ULONG bus_number, ULONG device_number, ULONG function_number, + ULONG offset, ULONG value, UINT write_size); +VOID *_ux_utility_physical_address(VOID *virtual_address); +UINT _ux_utility_semaphore_create(TX_SEMAPHORE *semaphore, CHAR *semaphore_name, UINT initial_count); +UINT _ux_utility_semaphore_delete(TX_SEMAPHORE *semaphore); +UINT _ux_utility_semaphore_get(TX_SEMAPHORE *semaphore, ULONG semaphore_signal); +UINT _ux_utility_semaphore_put(TX_SEMAPHORE *semaphore); +VOID _ux_utility_set_interrupt_handler(UINT irq, VOID (*interrupt_handler)(VOID)); +ULONG _ux_utility_short_get(UCHAR * address); +ULONG _ux_utility_short_get_big_endian(UCHAR * address); +VOID _ux_utility_short_put(UCHAR * address, USHORT value); +VOID _ux_utility_short_put_big_endian(UCHAR * address, USHORT value); +UINT _ux_utility_thread_create(TX_THREAD *thread_ptr, CHAR *name, + VOID (*entry_function)(ULONG), ULONG entry_input, + VOID *stack_start, ULONG stack_size, + UINT priority, UINT preempt_threshold, + ULONG time_slice, UINT auto_start); +UINT _ux_utility_thread_delete(TX_THREAD *thread_ptr); +VOID _ux_utility_thread_relinquish(VOID); +UINT _ux_utility_thread_schedule_other(UINT caller_priority); +UINT _ux_utility_thread_resume(TX_THREAD *thread_ptr); +UINT _ux_utility_thread_sleep(ULONG ticks); +UINT _ux_utility_thread_suspend(TX_THREAD *thread_ptr); +TX_THREAD *_ux_utility_thread_identify(VOID); +UINT _ux_utility_timer_create(TX_TIMER *timer, CHAR *timer_name, VOID (*expiration_function) (ULONG), + ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, + UINT activation_flag); +VOID *_ux_utility_virtual_address(VOID *physical_address); +UINT _ux_utility_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name); +UINT _ux_utility_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr); +UINT _ux_utility_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags, + UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option); +UINT _ux_utility_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, + UINT set_option); +VOID _ux_utility_unicode_to_string(UCHAR *source, UCHAR *destination); +VOID _ux_utility_string_to_unicode(UCHAR *source, UCHAR *destination); +VOID _ux_system_error_handler(UINT system_level, UINT system_context, UINT error_code); +VOID _ux_utility_debug_callback_register(VOID (*debug_callback)(UCHAR *, ULONG)); +VOID _ux_utility_error_callback_register(VOID (*error_callback)(UINT system_level, UINT system_context, UINT error_code)); +VOID _ux_utility_delay_ms(ULONG ms_wait); + +#define UX_UTILITY_ADD_SAFE(add_a, add_b, result, status) do { \ + if (UX_OVERFLOW_CHECK_ADD_ULONG(add_a, add_b)) \ + status = UX_ERROR; \ + else \ + result = (add_a) + (add_b); \ + } while(0) + +#define UX_UTILITY_MULC_SAFE(mul_v, mul_c, result, status) do { \ + if (UX_OVERFLOW_CHECK_MULC_ULONG(mul_v, mul_c)) \ + status = UX_ERROR; \ + else \ + result = (mul_v) * (mul_c); \ + } while(0) + +#define UX_UTILITY_MULV_SAFE(mul_v0, mul_v1, result, status) do { \ + if (UX_OVERFLOW_CHECK_MULC_ULONG(mul_v0, mul_v1)) \ + status = UX_ERROR; \ + else \ + result = (mul_v0) * (mul_v1); \ + } while(0) + +#define UX_UTILITY_MEMORY_ALLOCATE_MULC_SAFE(align,cache,size_mul_v,size_mul_c) \ + (UX_OVERFLOW_CHECK_MULC_ULONG(size_mul_v, size_mul_c) ? UX_NULL : _ux_utility_memory_allocate((align), (cache), (size_mul_v)*(size_mul_c))) +#define UX_UTILITY_MEMORY_ALLOCATE_MULV_SAFE(align,cache,size_mul_v0,size_mul_v1) \ + (UX_OVERFLOW_CHECK_MULV_ULONG(size_mul_v0, size_mul_v1) ? UX_NULL : _ux_utility_memory_allocate((align), (cache), (size_mul_v0)*(size_mul_v1))) +#define UX_UTILITY_MEMORY_ALLOCATE_ADD_SAFE(align,cache,size_add_a,size_add_b) \ + (UX_OVERFLOW_CHECK_ADD_ULONG(size_add_a, size_add_b) ? UX_NULL : _ux_utility_memory_allocate((align), (cache), (size_add_a)+(size_add_b))) + +#ifdef UX_DISABLE_ARITHMETIC_CHECK + +/* No arithmetic check, calculate directly. */ + +#define _ux_utility_memory_allocate_mulc_safe(align,cache,size_mul_v,size_mul_c) _ux_utility_memory_allocate((align), (cache), (size_mul_v)*(size_mul_c)) +#define _ux_utility_memory_allocate_mulv_safe(align,cache,size_mul_v0,size_mul_v1) _ux_utility_memory_allocate((align), (cache), (size_mul_v0)*(size_mul_v1)) +#define _ux_utility_memory_allocate_add_safe(align,cache,size_add_a,size_add_b) _ux_utility_memory_allocate((align), (cache), (size_add_a)+(size_add_b)) + +#else /* UX_DISABLE_ARITHMETIC_CHECK */ + +#ifdef UX_ENABLE_MEMORY_ARITHMETIC_OPTIMIZE + +/* Uses macro to enable code optimization on compiling. */ + +#define _ux_utility_memory_allocate_mulc_safe(align,cache,size_mul_v,size_mul_c) UX_UTILITY_MEMORY_ALLOCATE_MULC_SAFE(align,cache,size_mul_v,size_mul_c) +#define _ux_utility_memory_allocate_mulv_safe(align,cache,size_mul_v0,size_mul_v1) UX_UTILITY_MEMORY_ALLOCATE_MULV_SAFE(align,cache,size_mul_v0,size_mul_v1) +#define _ux_utility_memory_allocate_add_safe(align,cache,size_add_a,size_add_b) UX_UTILITY_MEMORY_ALLOCATE_ADD_SAFE(align,cache,size_add_a,size_add_b) + +#else /* UX_ENABLE_MEMORY_ARITHMETIC_OPTIMIZE */ + +/* Uses functions to be most flexible. */ + +VOID* _ux_utility_memory_allocate_mulc_safe(ULONG align,ULONG cache,ULONG size_mul_v,ULONG size_mul_c); +VOID* _ux_utility_memory_allocate_mulv_safe(ULONG align,ULONG cache,ULONG size_mul_v0,ULONG size_mul_v1); +VOID* _ux_utility_memory_allocate_add_safe(ULONG align,ULONG cache,ULONG size_add_a,ULONG size_add_b); + +#endif /* UX_ENABLE_MEMORY_ARITHMETIC_OPTIMIZE */ + +#endif /* UX_DISABLE_ARITHMETIC_CHECK */ + +/* Define the system API mappings. + Note: this section is only applicable to + application source code, hence the conditional that turns off this + stuff when the include file is processed by the ThreadX source. */ + +#ifndef UX_SOURCE_CODE + + +#define ux_utility_descriptor_parse _ux_utility_descriptor_parse +#define ux_utility_descriptor_pack _ux_utility_descriptor_pack +#define ux_utility_long_get _ux_utility_long_get +#define ux_utility_long_put _ux_utility_long_put +#define ux_utility_long_put_big_endian _ux_utility_long_put_big_endian +#define ux_utility_long_get_big_endian _ux_utility_long_get_big_endian +#define ux_utility_memory_allocate _ux_utility_memory_allocate +#define ux_utility_memory_compare _ux_utility_memory_compare +#define ux_utility_memory_copy _ux_utility_memory_copy +#define ux_utility_memory_free _ux_utility_memory_free +#define ux_utility_string_length_get _ux_utility_string_length_get +#define ux_utility_string_length_check _ux_utility_string_length_check +#define ux_utility_memory_set _ux_utility_memory_set +#define ux_utility_mutex_create _ux_utility_mutex_create +#define ux_utility_mutex_delete _ux_utility_mutex_delete +#define ux_utility_mutex_off _ux_utility_mutex_off +#define ux_utility_mutex_on _ux_utility_mutex_on +#define ux_utility_pci_class_scan _ux_utility_pci_class_scan +#define ux_utility_pci_read _ux_utility_pci_read +#define ux_utility_pci_write _ux_utility_pci_write +#define ux_utility_physical_address _ux_utility_physical_address +#define ux_utility_semaphore_create _ux_utility_semaphore_create +#define ux_utility_semaphore_delete _ux_utility_semaphore_delete +#define ux_utility_semaphore_get _ux_utility_semaphore_get +#define ux_utility_semaphore_put _ux_utility_semaphore_put +#define ux_utility_set_interrupt_handler _ux_utility_set_interrupt_handler +#define ux_utility_short_get _ux_utility_short_get +#define ux_utility_short_get_big_endian _ux_utility_short_get_big_endian +#define ux_utility_short_put _ux_utility_short_put +#define ux_utility_short_put_big_endian _ux_utility_short_put_big_endian +#define ux_utility_thread_create _ux_utility_thread_create +#define ux_utility_thread_delete _ux_utility_thread_delete +#define ux_utility_thread_relinquish _ux_utility_thread_relinquish +#define ux_utility_thread_resume _ux_utility_thread_resume +#define ux_utility_thread_sleep _ux_utility_thread_sleep +#define ux_utility_thread_suspend _ux_utility_thread_suspend +#define ux_utility_thread_identify _ux_utility_thread_identify +#define ux_utility_timer_create _ux_utility_timer_create +#define ux_utility_event_flags_create _ux_utility_event_flags_create +#define ux_utility_event_flags_delete _ux_utility_event_flags_delete +#define ux_utility_event_flags_get _ux_utility_event_flags_get +#define ux_utility_event_flags_set _ux_utility_event_flags_set +#define ux_utility_unicode_to_string _ux_utility_unicode_to_string +#define ux_utility_string_to_unicode _ux_utility_string_to_unicode +#define ux_utility_delay_ms _ux_utility_delay_ms +#define ux_utility_error_callback_register _ux_utility_error_callback_register +#define ux_system_error_handler _ux_system_error_handler +#endif + +#endif diff --git a/common/core/src/ux_dcd_sim_slave_address_set.c b/common/core/src/ux_dcd_sim_slave_address_set.c new file mode 100644 index 0000000..703312e --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_address_set.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_address_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will set the address of the device after we have */ +/* received a SET_ADDRESS command from the host. */ +/* */ +/* INPUT */ +/* */ +/* dcd_sim_slave Pointer to device controller */ +/* address Address to set */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_address_set(UX_DCD_SIM_SLAVE *dcd_sim_slave, ULONG address) +{ + + UX_PARAMETER_NOT_USED(dcd_sim_slave); + UX_PARAMETER_NOT_USED(address); + + /* This function always succeeds. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_dcd_sim_slave_endpoint_create.c b/common/core/src/ux_dcd_sim_slave_endpoint_create.c new file mode 100644 index 0000000..3dcc2d2 --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_endpoint_create.c @@ -0,0 +1,114 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_endpoint_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will create a physical endpoint. */ +/* */ +/* INPUT */ +/* */ +/* dcd_sim_slave Pointer to device controller */ +/* endpoint Pointer to endpoint container */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_endpoint_create(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_ENDPOINT *endpoint) +{ + +UX_DCD_SIM_SLAVE_ED *ed; +ULONG sim_slave_endpoint_index; + + + /* The simulator slave controller has 16 endpoints maximum. Endpoint 0 is always control. + The other endpoints are generic. We can use the endpoint number as an index. */ + sim_slave_endpoint_index = endpoint ->ux_slave_endpoint_descriptor.bEndpointAddress & ~(ULONG)UX_ENDPOINT_DIRECTION; + + /* Fetch the address of the physical endpoint. */ + ed = &dcd_sim_slave -> ux_dcd_sim_slave_ed[sim_slave_endpoint_index]; + + /* Check the endpoint status, if it is free, reserve it. If not reject this endpoint. */ + if ((ed -> ux_sim_slave_ed_status & UX_DCD_SIM_SLAVE_ED_STATUS_USED) == 0) + { + + /* We can use this endpoint. */ + ed -> ux_sim_slave_ed_status |= UX_DCD_SIM_SLAVE_ED_STATUS_USED; + + /* Keep the physical endpoint address in the endpoint container. */ + endpoint -> ux_slave_endpoint_ed = (VOID *) ed; + + /* And its mask. */ + ed -> ux_sim_slave_ed_index = sim_slave_endpoint_index; + + /* Save the endpoint pointer. */ + ed -> ux_sim_slave_ed_endpoint = endpoint; + + /* If this is endpoint 0, it is always ready for transactions. */ + if ( sim_slave_endpoint_index == 0) + ed -> ux_sim_slave_ed_status |= UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER; + + /* Enable this endpoint. */ + return(UX_SUCCESS); + } + + /* Notify application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_DCD, UX_MEMORY_INSUFFICIENT); + + /* Return error to caller. */ + return(UX_NO_ED_AVAILABLE); +} + diff --git a/common/core/src/ux_dcd_sim_slave_endpoint_destroy.c b/common/core/src/ux_dcd_sim_slave_endpoint_destroy.c new file mode 100644 index 0000000..0fabe5f --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_endpoint_destroy.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_endpoint_destroy PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will destroy a physical endpoint. */ +/* */ +/* INPUT */ +/* */ +/* dcd_sim_slave Pointer to device controller */ +/* endpoint Pointer to endpoint container */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_endpoint_destroy(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_ENDPOINT *endpoint) +{ + +UX_DCD_SIM_SLAVE_ED *ed; + + UX_PARAMETER_NOT_USED(dcd_sim_slave); + + /* Keep the physical endpoint address in the endpoint container. */ + ed = (UX_DCD_SIM_SLAVE_ED *) endpoint -> ux_slave_endpoint_ed; + + /* We can free this endpoint. */ + ed -> ux_sim_slave_ed_status = UX_DCD_SIM_SLAVE_ED_STATUS_UNUSED; + + /* This function never fails. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_dcd_sim_slave_endpoint_reset.c b/common/core/src/ux_dcd_sim_slave_endpoint_reset.c new file mode 100644 index 0000000..a2659f6 --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_endpoint_reset.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_endpoint_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will reset a physical endpoint. */ +/* */ +/* INPUT */ +/* */ +/* dcd_sim_slave Pointer to device controller */ +/* endpoint Pointer to endpoint container */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_endpoint_reset(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_ENDPOINT *endpoint) +{ + +UX_DCD_SIM_SLAVE_ED *ed; + + UX_PARAMETER_NOT_USED(dcd_sim_slave); + + /* Get the physical endpoint address in the endpoint container. */ + ed = (UX_DCD_SIM_SLAVE_ED *) endpoint -> ux_slave_endpoint_ed; + + /* Set the state of the endpoint to not stalled. */ + ed -> ux_sim_slave_ed_status &= ~(ULONG)UX_DCD_SIM_SLAVE_ED_STATUS_STALLED; + + /* This function never fails. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_dcd_sim_slave_endpoint_stall.c b/common/core/src/ux_dcd_sim_slave_endpoint_stall.c new file mode 100644 index 0000000..00c53f0 --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_endpoint_stall.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_endpoint_stall PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will stall a physical endpoint. */ +/* */ +/* INPUT */ +/* */ +/* dcd_sim_slave Pointer to device controller */ +/* endpoint Pointer to endpoint container */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_endpoint_stall(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_ENDPOINT *endpoint) +{ + +UX_DCD_SIM_SLAVE_ED *ed; + + UX_PARAMETER_NOT_USED(dcd_sim_slave); + + /* Get the physical endpoint address in the endpoint container. */ + ed = (UX_DCD_SIM_SLAVE_ED *) endpoint -> ux_slave_endpoint_ed; + + /* Set the state of the endpoint to stalled. */ + ed -> ux_sim_slave_ed_status |= UX_DCD_SIM_SLAVE_ED_STATUS_STALLED; + + /* This function never fails. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_dcd_sim_slave_endpoint_status.c b/common/core/src/ux_dcd_sim_slave_endpoint_status.c new file mode 100644 index 0000000..1830cb6 --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_endpoint_status.c @@ -0,0 +1,89 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_endpoint_status PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will return the status of the endpoint. */ +/* */ +/* INPUT */ +/* */ +/* dcd_sim_slave Pointer to device controller */ +/* endpoint_index Endpoint index */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_endpoint_status(UX_DCD_SIM_SLAVE *dcd_sim_slave, ULONG endpoint_index) +{ + +UX_DCD_SIM_SLAVE_ED *ed; + + + /* Fetch the address of the physical endpoint. */ + ed = &dcd_sim_slave -> ux_dcd_sim_slave_ed[endpoint_index]; + + /* Check the endpoint status, if it is free, we have a illegal endpoint. */ + if ((ed -> ux_sim_slave_ed_status & UX_DCD_SIM_SLAVE_ED_STATUS_USED) == 0) + return(UX_ERROR); + + /* Check if the endpoint is stalled. */ + if ((ed -> ux_sim_slave_ed_status & UX_DCD_SIM_SLAVE_ED_STATUS_STALLED) == 0) + return(UX_FALSE); + else + return(UX_TRUE); +} + diff --git a/common/core/src/ux_dcd_sim_slave_frame_number_get.c b/common/core/src/ux_dcd_sim_slave_frame_number_get.c new file mode 100644 index 0000000..6f87b2d --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_frame_number_get.c @@ -0,0 +1,82 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_frame_number_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will return the frame number currently used by the */ +/* controller. This function is mostly used for isochronous purposes. */ +/* */ +/* INPUT */ +/* */ +/* dcd_sim_slave Pointer to device controller */ +/* frame_number Destination for frame number */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_frame_number_get(UX_DCD_SIM_SLAVE *dcd_sim_slave, ULONG *frame_number) +{ + + UX_PARAMETER_NOT_USED(dcd_sim_slave); + + /* There is no frame number from the slave controller. */ + *frame_number = 0; + + /* This function never fails. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_dcd_sim_slave_function.c b/common/core/src/ux_dcd_sim_slave_function.c new file mode 100644 index 0000000..bd58839 --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_function.c @@ -0,0 +1,172 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_function PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function dispatches the DCD function internally to the */ +/* slave simulator controller. */ +/* */ +/* INPUT */ +/* */ +/* dcd Pointer to device controller */ +/* function Function requested */ +/* parameter Pointer to parameter structure*/ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_dcd_sim_slave_address_set Set address */ +/* _ux_dcd_sim_slave_endpoint_create Create endpoint */ +/* _ux_dcd_sim_slave_endpoint_destroy Destroy endpoint */ +/* _ux_dcd_sim_slave_endpoint_reset Reset endpoint */ +/* _ux_dcd_sim_slave_endpoint_stall Stall endpoint */ +/* _ux_dcd_sim_slave_endpoint_status Get endpoint status */ +/* _ux_dcd_sim_slave_frame_number_get Get frame number */ +/* _ux_dcd_sim_slave_state_change Change state */ +/* _ux_dcd_sim_slave_transfer_abort Abort transfer */ +/* _ux_dcd_sim_slave_transfer_request Request transfer */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_function(UX_SLAVE_DCD *dcd, UINT function, VOID *parameter) +{ + +UINT status; +UX_DCD_SIM_SLAVE *dcd_sim_slave; + + + /* Check the status of the controller. */ + if (dcd -> ux_slave_dcd_status == UX_UNUSED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_DCD, UX_CONTROLLER_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONTROLLER_UNKNOWN, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONTROLLER_UNKNOWN); + } + + /* Get the pointer to the Slave simulation DCD. */ + dcd_sim_slave = (UX_DCD_SIM_SLAVE *) dcd -> ux_slave_dcd_controller_hardware; + + /* Look at the function and route it. */ + switch(function) + { + + case UX_DCD_GET_FRAME_NUMBER: + + status = _ux_dcd_sim_slave_frame_number_get(dcd_sim_slave, (ULONG *) parameter); + break; + + case UX_DCD_TRANSFER_REQUEST: + + status = _ux_dcd_sim_slave_transfer_request(dcd_sim_slave, (UX_SLAVE_TRANSFER *) parameter); + break; + + case UX_DCD_TRANSFER_ABORT: + + status = _ux_dcd_sim_slave_transfer_abort(dcd_sim_slave, (UX_SLAVE_TRANSFER *) parameter); + break; + + case UX_DCD_CREATE_ENDPOINT: + + status = _ux_dcd_sim_slave_endpoint_create(dcd_sim_slave, parameter); + break; + + case UX_DCD_DESTROY_ENDPOINT: + + status = _ux_dcd_sim_slave_endpoint_destroy(dcd_sim_slave, parameter); + break; + + case UX_DCD_RESET_ENDPOINT: + + status = _ux_dcd_sim_slave_endpoint_reset(dcd_sim_slave, parameter); + break; + + case UX_DCD_STALL_ENDPOINT: + + status = _ux_dcd_sim_slave_endpoint_stall(dcd_sim_slave, parameter); + break; + + case UX_DCD_SET_DEVICE_ADDRESS: + + status = _ux_dcd_sim_slave_address_set(dcd_sim_slave, (ULONG) (ALIGN_TYPE) parameter); + break; + + case UX_DCD_CHANGE_STATE: + + status = _ux_dcd_sim_slave_state_change(dcd_sim_slave, (ULONG) (ALIGN_TYPE) parameter); + break; + + case UX_DCD_ENDPOINT_STATUS: + + status = _ux_dcd_sim_slave_endpoint_status(dcd_sim_slave, (ULONG) (ALIGN_TYPE) parameter); + break; + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_DCD, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + status = UX_FUNCTION_NOT_SUPPORTED; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_dcd_sim_slave_initialize.c b/common/core/src/ux_dcd_sim_slave_initialize.c new file mode 100644 index 0000000..4499ae6 --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_initialize.c @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB simulation slave controller. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_initialize(VOID) +{ + +UX_SLAVE_DCD *dcd; +UX_DCD_SIM_SLAVE *dcd_sim_slave; + + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* The controller initialized here is of Slave simulation type. */ + dcd -> ux_slave_dcd_controller_type = UX_DCD_SIM_SLAVE_SLAVE_CONTROLLER; + + /* Allocate memory for this Slave simulation DCD instance. */ + dcd_sim_slave = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_DCD_SIM_SLAVE)); + + /* Check if memory was properly allocated. */ + if(dcd_sim_slave == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Set the pointer to the Slave simulation DCD. */ + dcd -> ux_slave_dcd_controller_hardware = (VOID *) dcd_sim_slave; + + /* Set the generic DCD owner for the Slave simulation DCD. */ + dcd_sim_slave -> ux_dcd_sim_slave_dcd_owner = dcd; + + /* Initialize the function collector for this DCD. */ + dcd -> ux_slave_dcd_function = _ux_dcd_sim_slave_function; + + /* Set the state of the controller to OPERATIONAL now. */ + dcd -> ux_slave_dcd_status = UX_DCD_STATUS_OPERATIONAL; + + /* This operation completed with success. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_dcd_sim_slave_initialize_complete.c b/common/core/src/ux_dcd_sim_slave_initialize_complete.c new file mode 100644 index 0000000..7e22c85 --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_initialize_complete.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_initialize_complete PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function completes the initialization of the slave controller */ +/* simulator. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_initialize_complete(VOID) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_DEVICE *device; +UCHAR * device_framework; +UX_SLAVE_TRANSFER *transfer_request; + + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Slave simulator is a Full speed controller. */ + _ux_system_slave -> ux_system_slave_device_framework = _ux_system_slave -> ux_system_slave_device_framework_full_speed; + _ux_system_slave -> ux_system_slave_device_framework_length = _ux_system_slave -> ux_system_slave_device_framework_length_full_speed; + + /* Get the device framework pointer. */ + device_framework = _ux_system_slave -> ux_system_slave_device_framework; + + /* And create the decompressed device descriptor structure. */ + _ux_utility_descriptor_parse(device_framework, + _ux_system_device_descriptor_structure, + UX_DEVICE_DESCRIPTOR_ENTRIES, + (UCHAR *) &device -> ux_slave_device_descriptor); + + /* Now we create a transfer request to accept the first SETUP packet + and get the ball running. First get the address of the endpoint + transfer request container. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Set the timeout to be for Control Endpoint. */ + transfer_request -> ux_slave_transfer_request_timeout = MS_TO_TICK(UX_CONTROL_TRANSFER_TIMEOUT); + + /* Adjust the current data pointer as well. */ + transfer_request -> ux_slave_transfer_request_current_data_pointer = + transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Update the transfer request endpoint pointer with the default endpoint. */ + transfer_request -> ux_slave_transfer_request_endpoint = &device -> ux_slave_device_control_endpoint; + + /* The control endpoint max packet size needs to be filled manually in its descriptor. */ + transfer_request -> ux_slave_transfer_request_endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize = + device -> ux_slave_device_descriptor.bMaxPacketSize0; + + /* On the control endpoint, always expect the maximum. */ + transfer_request -> ux_slave_transfer_request_requested_length = + device -> ux_slave_device_descriptor.bMaxPacketSize0; + + /* Attach the control endpoint to the transfer request. */ + transfer_request -> ux_slave_transfer_request_endpoint = &device -> ux_slave_device_control_endpoint; + + /* Create the default control endpoint attached to the device. + Once this endpoint is enabled, the host can then send a setup packet + The device controller will receive it and will call the setup function + module. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_CREATE_ENDPOINT, + (VOID *) &device -> ux_slave_device_control_endpoint); + + /* Ensure the control endpoint is properly reset. */ + device -> ux_slave_device_control_endpoint.ux_slave_endpoint_state = UX_ENDPOINT_RESET; + + /* A SETUP packet is a DATA IN operation. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_IN; + + /* We are now ready for the USB device to accept the first packet when connected. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_dcd_sim_slave_state_change.c b/common/core/src/ux_dcd_sim_slave_state_change.c new file mode 100644 index 0000000..eacd3d8 --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_state_change.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_state_change PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will set the state of the controller to the desired */ +/* value. */ +/* */ +/* INPUT */ +/* */ +/* dcd_sim_slave Pointer to device controller */ +/* state Desired state */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_state_change(UX_DCD_SIM_SLAVE *dcd_sim_slave, ULONG state) +{ + + UX_PARAMETER_NOT_USED(dcd_sim_slave); + UX_PARAMETER_NOT_USED(state); + + /* Nothing to do in simulation mode. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_dcd_sim_slave_transfer_abort.c b/common/core/src/ux_dcd_sim_slave_transfer_abort.c new file mode 100644 index 0000000..f3c56b4 --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_transfer_abort.c @@ -0,0 +1,90 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_transfer_abort PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will terminate a transfer. */ +/* */ +/* INPUT */ +/* */ +/* dcd_sim_slave Pointer to device controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_transfer_abort(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_TRANSFER *transfer_request) +{ + +UX_DCD_SIM_SLAVE_ED *ed; +UX_SLAVE_ENDPOINT *endpoint; + + UX_PARAMETER_NOT_USED(dcd_sim_slave); + + /* Get the pointer to the logical endpoint from the transfer request. */ + endpoint = transfer_request -> ux_slave_transfer_request_endpoint; + + /* Keep the physical endpoint address in the endpoint container. */ + ed = (UX_DCD_SIM_SLAVE_ED *) endpoint -> ux_slave_endpoint_ed; + + /* Turn off the transfer bit. */ + ed -> ux_sim_slave_ed_status &= ~(ULONG)UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER; + + /* This function never fails. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_dcd_sim_slave_transfer_request.c b/common/core/src/ux_dcd_sim_slave_transfer_request.c new file mode 100644 index 0000000..5e1d530 --- /dev/null +++ b/common/core/src/ux_dcd_sim_slave_transfer_request.c @@ -0,0 +1,123 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Slave Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_dcd_sim_slave.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_dcd_sim_slave_transfer_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will initiate a transfer to a specific endpoint. */ +/* If the endpoint is IN, the endpoint register will be set to accept */ +/* the request. */ +/* */ +/* If the endpoint is IN, the endpoint FIFO will be filled with the */ +/* buffer and the endpoint register set. */ +/* */ +/* INPUT */ +/* */ +/* dcd_sim_slave Pointer to device controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_dcd_sim_slave_transfer_abort Abort transfer */ +/* */ +/* CALLED BY */ +/* */ +/* Slave Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_dcd_sim_slave_transfer_request(UX_DCD_SIM_SLAVE *dcd_sim_slave, UX_SLAVE_TRANSFER *transfer_request) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_DCD_SIM_SLAVE_ED *ed; +UINT status; + + + /* Get the pointer to the logical endpoint from the transfer request. */ + endpoint = transfer_request -> ux_slave_transfer_request_endpoint; + + /* Get the slave endpoint. */ + ed = (UX_DCD_SIM_SLAVE_ED *) endpoint -> ux_slave_endpoint_ed; + + /* We have a request for a OUT or IN transaction from the host. + If the endpoint is a Control endpoint, all this is happening under Interrupt and there is no + thread to suspend. */ + if (ed -> ux_sim_slave_ed_index != 0) + { + + /* Set the ED to TRANSFER status. */ + ed -> ux_sim_slave_ed_status |= UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER; + + /* We should wait for the semaphore to wake us up. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_slave_transfer_request_semaphore, + transfer_request -> ux_slave_transfer_request_timeout); + + /* Reset the ED to TRANSFER status. */ + ed -> ux_sim_slave_ed_status &= ~(ULONG)UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER; + + /* Check the completion code. */ + if (status != UX_SUCCESS) + { + _ux_dcd_sim_slave_transfer_abort(dcd_sim_slave, transfer_request); + transfer_request -> ux_slave_transfer_request_status = UX_TRANSFER_STATUS_COMPLETED; + return(status); + } + + /* Check the transfer request completion code. We may have had a BUS reset or + a device disconnection. */ + if (transfer_request -> ux_slave_transfer_request_completion_code != UX_SUCCESS) + return(transfer_request -> ux_slave_transfer_request_completion_code); + } + + /* Return to caller with success. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_device_class_dpump_activate.c b/common/core/src/ux_device_class_dpump_activate.c new file mode 100644 index 0000000..1e0d307 --- /dev/null +++ b/common/core/src/ux_device_class_dpump_activate.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dpump.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dpump_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function activates the USB dpump device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to dpump command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Device Data Pump Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dpump_activate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_DPUMP *dpump; +UX_SLAVE_CLASS *class; +UX_SLAVE_ENDPOINT *endpoint; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Store the class instance in the container. */ + dpump = (UX_SLAVE_CLASS_DPUMP *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Store the class instance into the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)dpump; + + /* Now the opposite, store the interface in the class instance. */ + dpump -> ux_slave_class_dpump_interface = interface; + + /* Locate the endpoints. Interrupt for Control and Bulk in/out for Data. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Parse all endpoints. */ + while (endpoint != UX_NULL) + { + + /* Check the endpoint direction, and type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) + { + + /* Look at type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT) + + /* We have found the bulk in endpoint, save it. */ + dpump -> ux_slave_class_dpump_bulkin_endpoint = endpoint; + + } + else + { + /* Look at type for out endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT) + + /* We have found the bulk out endpoint, save it. */ + dpump -> ux_slave_class_dpump_bulkout_endpoint = endpoint; + } + + /* Next endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + + /* If there is a activate function call it. */ + if (dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_activate != UX_NULL) + { + + /* Invoke the application. */ + dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_activate(dpump); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DPUMP_ACTIVATE, dpump, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, dpump, 0, 0, 0) + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_device_class_dpump_change.c b/common/core/src/ux_device_class_dpump_change.c new file mode 100644 index 0000000..e4e759a --- /dev/null +++ b/common/core/src/ux_device_class_dpump_change.c @@ -0,0 +1,168 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device DPUMP Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dpump.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dpump_change PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function changes the interface of the DPUMP device */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to dpump command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_set Set memory */ +/* _ux_device_stack_transfer_all_request_abort */ +/* Abort request */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dpump_change(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_DPUMP *dpump; +UX_SLAVE_CLASS *class; +UX_SLAVE_ENDPOINT *endpoint; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + dpump = (UX_SLAVE_CLASS_DPUMP *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Locate the endpoints. Control and Bulk in/out for data. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Keep the alternate setting in the dpump structure. */ + dpump -> ux_slave_class_dpump_alternate_setting = interface -> ux_slave_interface_descriptor.bAlternateSetting; + + /* If the interface to mount has a non zero alternate setting, the class is really active with + the endpoints active. If the interface reverts to alternate setting 0, it needs to have + the pending transactions terminated. */ + if (interface -> ux_slave_interface_descriptor.bAlternateSetting != 0) + { + + /* Parse all endpoints. */ + while (endpoint != UX_NULL) + { + + /* Check the endpoint direction, and type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) + { + + /* Look at type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT) + + /* We have found the bulk in endpoint, save it. */ + dpump -> ux_slave_class_dpump_bulkin_endpoint = endpoint; + + } + else + { + /* Look at type for out endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT) + + /* We have found the bulk out endpoint, save it. */ + dpump -> ux_slave_class_dpump_bulkout_endpoint = endpoint; + } + + /* Next endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + + /* Now check if all endpoints have been found. */ + if (dpump -> ux_slave_class_dpump_bulkout_endpoint == UX_NULL || dpump -> ux_slave_class_dpump_bulkin_endpoint == UX_NULL) + + /* Not all endpoints have been found. Major error, do not proceed. */ + return(UX_ERROR); + + /* Reset the endpoint buffers. */ + _ux_utility_memory_set(dpump -> ux_slave_class_dpump_bulkout_endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + _ux_utility_memory_set(dpump -> ux_slave_class_dpump_bulkin_endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + + /* Keep the alternate setting in the dpump structure. */ + dpump -> ux_slave_class_dpump_alternate_setting = interface -> ux_slave_interface_descriptor.bAlternateSetting; + + /* If there is an activate function call it. */ + if (dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_activate != UX_NULL) + + /* Invoke the application. */ + dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_activate(dpump); + } + else + { + + /* In this case, we are reverting to the Alternate Setting 0. We need to terminate the pending transactions. */ + /* Terminate the transactions pending on the endpoints (bulk in, bulk out). */ + _ux_device_stack_transfer_all_request_abort(dpump -> ux_slave_class_dpump_bulkin_endpoint, UX_TRANSFER_APPLICATION_RESET); + _ux_device_stack_transfer_all_request_abort(dpump -> ux_slave_class_dpump_bulkout_endpoint, UX_TRANSFER_APPLICATION_RESET); + + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DPUMP_CHANGE, dpump, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, dpump, 0, 0, 0) + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_device_class_dpump_deactivate.c b/common/core/src/ux_device_class_dpump_deactivate.c new file mode 100644 index 0000000..420ae11 --- /dev/null +++ b/common/core/src/ux_device_class_dpump_deactivate.c @@ -0,0 +1,129 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dpump.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dpump_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivate an instance of the dpump class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_all_request_abort Abort all transfers */ +/* */ +/* CALLED BY */ +/* */ +/* Device Data Pump Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dpump_deactivate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_DPUMP *dpump; +UX_SLAVE_ENDPOINT *endpoint_in; +UX_SLAVE_ENDPOINT *endpoint_out; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Store the class instance in the container. */ + dpump = (UX_SLAVE_CLASS_DPUMP *) class -> ux_slave_class_instance; + + /* We need the interface to the class. */ + interface = dpump -> ux_slave_class_dpump_interface; + + /* Locate the endpoints. */ + endpoint_in = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint_in -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* Wrong direction, we found the OUT endpoint first. */ + endpoint_out = endpoint_in; + + /* So the next endpoint has to be the IN endpoint. */ + endpoint_in = endpoint_out -> ux_slave_endpoint_next_endpoint; + } + else + { + + /* We found the endpoint IN first, so next endpoint is OUT. */ + endpoint_out = endpoint_in -> ux_slave_endpoint_next_endpoint; + } + + /* Terminate the transactions pending on the endpoints. */ + _ux_device_stack_transfer_all_request_abort(endpoint_in, UX_TRANSFER_BUS_RESET); + _ux_device_stack_transfer_all_request_abort(endpoint_out, UX_TRANSFER_BUS_RESET); + + /* If there is a deactivate function call it. */ + if (dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_deactivate != UX_NULL) + { + + /* Invoke the application. */ + dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_deactivate(dpump); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DPUMP_DEACTIVATE, dpump, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(dpump); + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_device_class_dpump_entry.c b/common/core/src/ux_device_class_dpump_entry.c new file mode 100644 index 0000000..d91272d --- /dev/null +++ b/common/core/src/ux_device_class_dpump_entry.c @@ -0,0 +1,147 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dpump.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_class_device_dpump_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the device dpump class. It */ +/* will be called by the device stack enumeration module when the */ +/* host has sent a SET_CONFIGURATION command and the dpump interface */ +/* needs to be mounted. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_dpump_initialize Initialize dpump class */ +/* _ux_device_class_dpump_activate Activate dpump class */ +/* _ux_device_class_dpump_deactivate Deactivate dpump class */ +/* _ux_device_class_dpump_change Alternate setting change */ +/* */ +/* CALLED BY */ +/* */ +/* Device Data Pump Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dpump_entry(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_slave_class_command_request) + { + + case UX_SLAVE_CLASS_COMMAND_INITIALIZE: + + /* Call the init function of the DPUMP class. */ + status = _ux_device_class_dpump_initialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_QUERY: + + /* Check the CLASS definition in the interface descriptor. */ + if (command -> ux_slave_class_command_class == UX_SLAVE_CLASS_DPUMP_CLASS) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_SLAVE_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the host has sent a SET_CONFIGURATION command + and this interface has to be mounted. Both Bulk endpoints have to be mounted + and the dpump thread needs to be activated. */ + status = _ux_device_class_dpump_activate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_CHANGE: + + /* The change command is used when the host has sent a SET_INTERFACE command + to go from Alternate Setting 0 to 1 or revert to the default mode. */ + status = _ux_device_class_dpump_change(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted. + The device endpoints have to be dismounted and the dpump thread canceled. */ + status = _ux_device_class_dpump_deactivate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_REQUEST: + + /* Return the completion status. */ + return(UX_SUCCESS); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/core/src/ux_device_class_dpump_initialize.c b/common/core/src/ux_device_class_dpump_initialize.c new file mode 100644 index 0000000..8096878 --- /dev/null +++ b/common/core/src/ux_device_class_dpump_initialize.c @@ -0,0 +1,100 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dpump.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dpump_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB dpump device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to dpump command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Data Pump Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dpump_initialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_DPUMP *dpump; +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_DPUMP_PARAMETER *dpump_parameter; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Create an instance of the device dpump class. */ + dpump = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_DPUMP)); + + /* Check for successful allocation. */ + if (dpump == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save the address of the DPUMP instance inside the DPUMP container. */ + class -> ux_slave_class_instance = (VOID *) dpump; + + /* Get the pointer to the application parameters for the cdc class. */ + dpump_parameter = command -> ux_slave_class_command_parameter; + + /* Store the start and stop signals if needed by the application. */ + dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_activate = dpump_parameter -> ux_slave_class_dpump_instance_activate; + dpump -> ux_slave_class_dpump_parameter.ux_slave_class_dpump_instance_deactivate = dpump_parameter -> ux_slave_class_dpump_instance_deactivate; + + /* Return completion status. */ + return(UX_SUCCESS); +} + + diff --git a/common/core/src/ux_device_class_dpump_read.c b/common/core/src/ux_device_class_dpump_read.c new file mode 100644 index 0000000..2a607e4 --- /dev/null +++ b/common/core/src/ux_device_class_dpump_read.c @@ -0,0 +1,182 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device DPUMP Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dpump.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dpump_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the DPUMP class. */ +/* */ +/* INPUT */ +/* */ +/* dpump Address of dpump class */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dpump_read(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; +ULONG local_requested_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DPUMP_READ, dpump, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Locate the OUT endpoint. */ + endpoint = dpump -> ux_slave_class_dpump_bulkout_endpoint; + + /* Check endpoint. If NULL, we have not yet received the proper SET_INTERFACE command. */ + if (endpoint == UX_NULL) + { + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* All DPUMP reading are on the endpoint OUT, from the host. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Reset the actual length. */ + *actual_length = 0; + + /* Set return status to SUCCESS to make certain compilers happy. */ + status = UX_SUCCESS; + + /* Check if we need more transactions. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && requested_length != 0) + { + + /* Check if we have enough in the local buffer. */ + if (requested_length > UX_SLAVE_REQUEST_DATA_MAX_LENGTH) + + /* We have too much to transfer. */ + local_requested_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + else + + /* We can proceed with the demanded length. */ + local_requested_length = requested_length; + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, local_requested_length, local_requested_length); + + /* Check the status */ + if (status == UX_SUCCESS) + { + + /* We need to copy the buffer locally. */ + _ux_utility_memory_copy(buffer, transfer_request -> ux_slave_transfer_request_data_pointer, + local_requested_length); + + /* Next buffer address. */ + buffer += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + *actual_length += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Decrement what left has to be done. */ + requested_length -= transfer_request -> ux_slave_transfer_request_actual_length; + + } + else + + /* We got an error. */ + return(status); + } + + /* Check why we got here, either completion or device was extracted. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Device must have been extracted. */ + return (UX_TRANSFER_NO_ANSWER); + } + else + + /* Simply return the last transaction result. */ + return(status); +} + diff --git a/common/core/src/ux_device_class_dpump_thread.c b/common/core/src/ux_device_class_dpump_thread.c new file mode 100644 index 0000000..254ea75 --- /dev/null +++ b/common/core/src/ux_device_class_dpump_thread.c @@ -0,0 +1,165 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dpump.h" +#include "ux_device_stack.h" + +/* Remove compiling warning. */ +VOID _ux_device_class_dpump_thread(ULONG dpump_class); + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dpump_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the dpump class. */ +/* */ +/* INPUT */ +/* */ +/* class Address of dpump class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_thread_suspend Suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_dpump_thread(ULONG dpump_class) +{ + +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_DPUMP *dpump; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_ENDPOINT *endpoint_in; +UX_SLAVE_ENDPOINT *endpoint_out; +UINT status; +ULONG length; + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + + /* Cast properly the dpump instance. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_SLAVE_CLASS, dpump_class) + + /* Get the dpump instance from this class container. */ + dpump = (UX_SLAVE_CLASS_DPUMP *) class -> ux_slave_class_instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* This is the first time we are activated. We need the interface to the class. */ + interface = dpump -> ux_slave_class_dpump_interface; + + /* Locate the endpoints. */ + endpoint_in = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint_in -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* Wrong direction, we found the OUT endpoint first. */ + endpoint_out = endpoint_in; + + /* So the next endpoint has to be the IN endpoint. */ + endpoint_in = endpoint_out -> ux_slave_endpoint_next_endpoint; + } + else + { + + /* We found the endpoint IN first, so next endpoint is OUT. */ + endpoint_out = endpoint_in -> ux_slave_endpoint_next_endpoint; + } + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* We prepare to receive from the host on the OUT endpoint. */ + transfer_request = &endpoint_out -> ux_slave_endpoint_transfer_request; + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_DPUMP_PACKET_SIZE, UX_DEVICE_CLASS_DPUMP_PACKET_SIZE); + + /* Check the status */ + if (status == UX_SUCCESS) + { + + /* Obtain the length of the transaction. */ + length = transfer_request -> ux_slave_transfer_request_actual_length; + + /* Copy the buffer to the target in endpoint. */ + _ux_utility_memory_copy(endpoint_in -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer, + endpoint_out -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer, + length); + + /* Now we send the packet back to the host. On the endpoint In. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Sends the data payload back to the caller. */ + status = _ux_device_stack_transfer_request(transfer_request, length, length); + + /* Check error code. */ + if (status != UX_SUCCESS) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + } + } + + /* We need to suspend ourselves. We will be resumed by the + device enumeration module. */ + _ux_utility_thread_suspend(&class -> ux_slave_class_thread); + } +} + diff --git a/common/core/src/ux_device_class_dpump_write.c b/common/core/src/ux_device_class_dpump_write.c new file mode 100644 index 0000000..676bf69 --- /dev/null +++ b/common/core/src/ux_device_class_dpump_write.c @@ -0,0 +1,186 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device DPUMP Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dpump.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dpump_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the DPUMP class. */ +/* */ +/* INPUT */ +/* */ +/* dpump Address of dpump class */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_copy */ +/* _ux_device_stack_transfer_request */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dpump_write(UX_SLAVE_CLASS_DPUMP *dpump, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +ULONG local_requested_length; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DPUMP_WRITE, dpump, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Locate the IN endpoint. */ + endpoint = dpump -> ux_slave_class_dpump_bulkin_endpoint; + + /* Check endpoint. If NULL, we have not yet received the proper SET_INTERFACE command. */ + if (endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* We are writing to the IN endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Reset the actual length. */ + *actual_length = 0; + + /* Set return status to SUCCESS to make certain compilers happy. */ + status = UX_SUCCESS; + + /* Check if we need more transactions. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && requested_length != 0) + { + + /* Check if we have enough in the local buffer. */ + if (requested_length > UX_SLAVE_REQUEST_DATA_MAX_LENGTH) + + /* We have too much to transfer. */ + local_requested_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + else + + /* We can proceed with the demanded length. */ + local_requested_length = requested_length; + + /* On a out, we copy the buffer to the caller. Not very efficient but it makes the API + easier. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + buffer, local_requested_length); + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, local_requested_length, local_requested_length); + + /* Check the status */ + if (status == UX_SUCCESS) + { + + /* Next buffer address. */ + buffer += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + *actual_length += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Decrement what left has to be done. */ + requested_length -= transfer_request -> ux_slave_transfer_request_actual_length; + + } + + else + + /* We had an error, abort. */ + return(status); + } + + /* Check why we got here, either completion or device was extracted. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Device must have been extracted. */ + return (UX_TRANSFER_NO_ANSWER); + } + else + + /* Simply return the last transaction result. */ + return(status); + +} + diff --git a/common/core/src/ux_device_stack_alternate_setting_get.c b/common/core/src/ux_device_stack_alternate_setting_get.c new file mode 100644 index 0000000..8d26f59 --- /dev/null +++ b/common/core/src/ux_device_stack_alternate_setting_get.c @@ -0,0 +1,133 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_alternate_setting_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the alternate setting for a specific interface. */ +/* */ +/* INPUT */ +/* */ +/* endpoint Pointer to endpoint */ +/* interface_value Interface value */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_alternate_setting_get(ULONG interface_value) +{ + +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_ALTERNATE_SETTING_GET, interface_value, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* If the device was in the configured state, there may be interfaces + attached to the configuration. */ + if (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Obtain the pointer to the first interface attached. */ + interface = device -> ux_slave_device_first_interface; + + /* Start parsing each interface. */ + while (interface != UX_NULL) + { + + /* Check if this is the interface we have an inquiry for. */ + if (interface -> ux_slave_interface_descriptor.bInterfaceNumber == interface_value) + { + + /* Get the control endpoint of the device. */ + endpoint = &device -> ux_slave_device_control_endpoint; + + /* Get the pointer to the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Set the value of the alternate setting in the buffer. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = + (UCHAR) interface -> ux_slave_interface_descriptor.bAlternateSetting; + + /* Setup the length appropriately. */ + transfer_request -> ux_slave_transfer_request_requested_length = 1; + + /* Set the phase of the transfer to data out. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* Send the descriptor with the appropriate length to the host. */ + status = _ux_device_stack_transfer_request(transfer_request, 1, 1); + + /* Return the function status. */ + return(status); + } + + /* Get the next interface. */ + interface = interface -> ux_slave_interface_next_interface; + } + } + + /* Return error completion. */ + return(UX_ERROR); +} + diff --git a/common/core/src/ux_device_stack_alternate_setting_set.c b/common/core/src/ux_device_stack_alternate_setting_set.c new file mode 100644 index 0000000..5e67f76 --- /dev/null +++ b/common/core/src/ux_device_stack_alternate_setting_set.c @@ -0,0 +1,408 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_alternate_setting_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the alternate setting for a specific interface. */ +/* The previous interface is unmounted and all the endpoints */ +/* associated with the alternate setting are mounted. */ +/* */ +/* INPUT */ +/* */ +/* endpoint Pointer to endpoint */ +/* interface_value Interface value */ +/* alternate_setting_value Alternate setting value */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_device_stack_transfer_all_request_abort */ +/* Abort transfer */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_alternate_setting_set(ULONG interface_value, ULONG alternate_setting_value) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *device_framework; +ULONG device_framework_length; +ULONG descriptor_length; +UCHAR descriptor_type; +UX_CONFIGURATION_DESCRIPTOR configuration_descriptor; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_ENDPOINT *next_endpoint; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_ENDPOINT *endpoint_link; +ULONG endpoints_pool_number; +UX_SLAVE_CLASS_COMMAND class_command; +UX_SLAVE_CLASS *class; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_ALTERNATE_SETTING_SET, interface_value, alternate_setting_value, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave->ux_system_slave_dcd; + + /* We may have multiple configurations! */ + device_framework = _ux_system_slave -> ux_system_slave_device_framework; + device_framework_length = _ux_system_slave -> ux_system_slave_device_framework_length; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Protocol error must be reported when it's unconfigured */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + return UX_FUNCTION_NOT_SUPPORTED; + + /* Find the current interface. */ + interface = device -> ux_slave_device_first_interface; + + /* Scan all interfaces if any. */ + while (interface != UX_NULL) + { + + if (interface -> ux_slave_interface_descriptor.bInterfaceNumber == interface_value) + break; + else + interface = interface -> ux_slave_interface_next_interface; + } + + /* We must have found the interface pointer for the interface value + requested by the caller. */ + if (interface == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_INTERFACE_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_INTERFACE_HANDLE_UNKNOWN, interface, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_INTERFACE_HANDLE_UNKNOWN); + } + + /* If the host is requesting a change of alternate setting to the current one, + we do not need to do any work. */ + if (interface -> ux_slave_interface_descriptor.bAlternateSetting == alternate_setting_value) + return(UX_SUCCESS); + + /* Parse the device framework and locate a configuration descriptor. */ + while (device_framework_length != 0) + { + + /* Get the length of the current descriptor. */ + descriptor_length = (ULONG) *device_framework; + + /* And its length. */ + descriptor_type =* (device_framework + 1); + + /* Check if this is a configuration descriptor. */ + if (descriptor_type == UX_CONFIGURATION_DESCRIPTOR_ITEM) + { + + /* Parse the descriptor in something more readable. */ + _ux_utility_descriptor_parse(device_framework, + _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, + (UCHAR *) &configuration_descriptor); + + /* Now we need to check the configuration value. */ + if (configuration_descriptor.bConfigurationValue == device -> ux_slave_device_configuration_selected) + { + + /* Limit the search in current configuration descriptor. */ + device_framework_length = configuration_descriptor.wTotalLength; + + /* We have found the configuration value that was selected by the host + We need to scan all the interface descriptors following this + configuration descriptor and locate the interface for which the alternate + setting must be changed. */ + while (device_framework_length != 0) + { + + /* Get the length of the current descriptor. */ + descriptor_length = (ULONG) *device_framework; + + /* And its type. */ + descriptor_type = *(device_framework + 1); + + /* Check if this is an interface descriptor. */ + if (descriptor_type == UX_INTERFACE_DESCRIPTOR_ITEM) + { + + /* Parse the descriptor in something more readable. */ + _ux_utility_descriptor_parse(device_framework, + _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, + (UCHAR *) &interface_descriptor); + + /* Check if this is the interface we are searching. */ + if (interface_descriptor.bInterfaceNumber == interface_value && + interface_descriptor.bAlternateSetting == alternate_setting_value) + { + + /* We have found the right interface and alternate setting. Before + we mount all the endpoints for this interface, we need to + unmount the endpoints associated with the previous alternate setting. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + while (endpoint != UX_NULL) + { + + /* Abort any pending transfer. */ + _ux_device_stack_transfer_all_request_abort(endpoint, UX_TRANSFER_BUS_RESET); + + /* The device controller must be called to destroy the endpoint. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_DESTROY_ENDPOINT, (VOID *) endpoint); + + /* Get the next endpoint. */ + next_endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + + /* Free the endpoint. */ + endpoint -> ux_slave_endpoint_status = UX_UNUSED; + + /* Make sure the endpoint instance is now cleaned up. */ + endpoint -> ux_slave_endpoint_state = 0; + endpoint -> ux_slave_endpoint_next_endpoint = UX_NULL; + endpoint -> ux_slave_endpoint_interface = UX_NULL; + endpoint -> ux_slave_endpoint_device = UX_NULL; + + /* Now we refresh the endpoint pointer. */ + endpoint = next_endpoint; + } + + /* Now clear the interface endpoint entry. */ + interface -> ux_slave_interface_first_endpoint = UX_NULL; + + /* Point beyond the interface descriptor. */ + device_framework_length -= (ULONG) *device_framework; + device_framework += (ULONG) *device_framework; + + /* Parse the device framework and locate endpoint descriptor(s). */ + while (device_framework_length != 0) + { + + /* Get the length of the current descriptor. */ + descriptor_length = (ULONG) *device_framework; + + /* And its type. */ + descriptor_type = *(device_framework + 1); + + /* Check if this is an endpoint descriptor. */ + switch(descriptor_type) + { + + case UX_ENDPOINT_DESCRIPTOR_ITEM: + + /* Find a free endpoint in the pool and hook it to the + existing interface after it's created by DCD. */ + endpoint = device -> ux_slave_device_endpoints_pool; + endpoints_pool_number = device -> ux_slave_device_endpoints_pool_number; + while (endpoints_pool_number != 0) + { + /* Check if this endpoint is free. */ + if (endpoint -> ux_slave_endpoint_status == UX_UNUSED) + { + /* Mark this endpoint as used now. */ + endpoint -> ux_slave_endpoint_status = UX_USED; + break; + } + + /* Try the next endpoint. */ + endpoint++; + + /* Decrement the number of endpoints to scan from the pool. */ + endpoints_pool_number--; + } + + /* Did we find a free endpoint ? */ + if (endpoints_pool_number == 0) + return(UX_MEMORY_INSUFFICIENT); + + /* Parse the descriptor in something more readable. */ + _ux_utility_descriptor_parse(device_framework, + _ux_system_endpoint_descriptor_structure, + UX_ENDPOINT_DESCRIPTOR_ENTRIES, + (UCHAR *) &endpoint -> ux_slave_endpoint_descriptor); + + /* Now we create a transfer request to accept transfer on this endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* We store the endpoint in the transfer request as well. */ + transfer_request -> ux_slave_transfer_request_endpoint = endpoint; + + /* By default the timeout is infinite on request. */ + transfer_request -> ux_slave_transfer_request_timeout = UX_WAIT_FOREVER; + + /* Attach the interface to the endpoint. */ + endpoint -> ux_slave_endpoint_interface = interface; + + /* Attach the device to the endpoint. */ + endpoint -> ux_slave_endpoint_device = device; + + /* Create the endpoint at the DCD level. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_CREATE_ENDPOINT, (VOID *) endpoint); + + /* Do a sanity check on endpoint creation. */ + if (status != UX_SUCCESS) + { + + /* Error was returned, endpoint cannot be created. */ + endpoint -> ux_slave_endpoint_status = UX_UNUSED; + return(status); + } + + /* Attach this endpoint to the end of the endpoint chain. */ + if (interface -> ux_slave_interface_first_endpoint == UX_NULL) + { + + interface -> ux_slave_interface_first_endpoint = endpoint; + } + else + { + /* Multiple endpoints exist, so find the end of the chain. */ + endpoint_link = interface -> ux_slave_interface_first_endpoint; + while (endpoint_link -> ux_slave_endpoint_next_endpoint != UX_NULL) + endpoint_link = endpoint_link -> ux_slave_endpoint_next_endpoint; + endpoint_link -> ux_slave_endpoint_next_endpoint = endpoint; + } + + break; + + case UX_CONFIGURATION_DESCRIPTOR_ITEM: + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* We have found a new configuration or interface descriptor, this is the end of the current + interface. The search for the endpoints must be terminated as if it was the end of the + entire descriptor. */ + device_framework_length = descriptor_length; + + break; + + + default: + + /* We have found another descriptor embedded in the interface. Ignore it. */ + break; + } + + /* Adjust what is left of the device framework. */ + device_framework_length -= descriptor_length; + + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + + /* The interface descriptor in the current class must be changed to the new alternate setting. */ + _ux_utility_memory_copy(&interface -> ux_slave_interface_descriptor, &interface_descriptor, sizeof(UX_INTERFACE_DESCRIPTOR)); + + /* Get the class for the interface. */ + class = _ux_system_slave -> ux_system_slave_interface_class_array[interface -> ux_slave_interface_descriptor.bInterfaceNumber]; + + /* Check if class driver is available. */ + if (class == UX_NULL || class -> ux_slave_class_status == UX_UNUSED) + { + + return (UX_NO_CLASS_MATCH); + } + + /* The interface attached to this configuration must be changed at the class + level. */ + class_command.ux_slave_class_command_request = UX_SLAVE_CLASS_COMMAND_CHANGE; + class_command.ux_slave_class_command_interface = (VOID *) interface; + + /* And store it. */ + class_command.ux_slave_class_command_class_ptr = class; + + /* We can now memorize the interface pointer associated with this class. */ + class -> ux_slave_class_interface = interface; + + /* We have found a potential candidate. Call this registered class entry function to change the alternate setting. */ + status = class -> ux_slave_class_entry_function(&class_command); + + /* We are done here. */ + return(status); + } + } + + /* Adjust what is left of the device framework. */ + device_framework_length -= descriptor_length; + + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + + /* In case alter setting not found, report protocol error. */ + break; + } + } + + /* Adjust what is left of the device framework. */ + device_framework_length -= descriptor_length; + + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + + /* Return error completion. */ + return(UX_ERROR); +} + diff --git a/common/core/src/ux_device_stack_class_register.c b/common/core/src/ux_device_stack_class_register.c new file mode 100644 index 0000000..b65b725 --- /dev/null +++ b/common/core/src/ux_device_stack_class_register.c @@ -0,0 +1,151 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_class_register PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers a slave class to the slave stack. */ +/* */ +/* Note: The C string of class_name must be NULL-terminated and the */ +/* length of it (without the NULL-terminator itself) must be no larger */ +/* than UX_MAX_CLASS_NAME_LENGTH. */ +/* */ +/* INPUT */ +/* */ +/* class_name Name of class */ +/* class_function_entry Class entry function */ +/* configuration_number Configuration # for this class*/ +/* interface_number Interface # for this class */ +/* parameter Parameter specific for class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_string_length_check Check C string and return */ +/* its length if null-terminated */ +/* _ux_utility_memory_copy Memory copy */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_class_register(UCHAR *class_name, + UINT (*class_entry_function)(struct UX_SLAVE_CLASS_COMMAND_STRUCT *), + ULONG configuration_number, + ULONG interface_number, + VOID *parameter) +{ + +UX_SLAVE_CLASS *class; +ULONG class_index; +UINT status; +UX_SLAVE_CLASS_COMMAND command; +UINT class_name_length = 0; + + + /* Get the length of the class name (exclude null-terminator). */ + status = _ux_utility_string_length_check(class_name, &class_name_length, UX_MAX_CLASS_NAME_LENGTH); + if (status) + return(status); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_CLASS_REGISTER, class_name, interface_number, parameter, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* We need to parse the class table to find an empty spot. */ + class = _ux_system_slave -> ux_system_slave_class_array; + for (class_index = 0; class_index < _ux_system_slave -> ux_system_slave_max_class; class_index++) + { + + /* Check if this class is already used. */ + if (class -> ux_slave_class_status == UX_UNUSED) + { + + /* We have found a free container for the class. Copy the name (with null-terminator). */ + _ux_utility_memory_copy(class -> ux_slave_class_name, class_name, class_name_length + 1); + + /* Memorize the entry function of this class. */ + class -> ux_slave_class_entry_function = class_entry_function; + + /* Memorize the pointer to the application parameter. */ + class -> ux_slave_class_interface_parameter = parameter; + + /* Memorize the configuration number on which this instance will be called. */ + class -> ux_slave_class_configuration_number = configuration_number; + + /* Memorize the interface number on which this instance will be called. */ + class -> ux_slave_class_interface_number = interface_number; + + /* Build all the fields of the Class Command to initialize the class. */ + command.ux_slave_class_command_request = UX_SLAVE_CLASS_COMMAND_INITIALIZE; + command.ux_slave_class_command_parameter = parameter; + command.ux_slave_class_command_class_ptr = class; + + /* Call the class initialization routine. */ + status = class_entry_function(&command); + + /* Check the status. */ + if (status != UX_SUCCESS) + return(status); + + /* Make this class used now. */ + class -> ux_slave_class_status = UX_USED; + + /* Return successful completion. */ + return(UX_SUCCESS); + } + + /* Move to the next class. */ + class++; + } + + /* No more entries in the class table. */ + return(UX_MEMORY_INSUFFICIENT); +} + diff --git a/common/core/src/ux_device_stack_class_unregister.c b/common/core/src/ux_device_stack_class_unregister.c new file mode 100644 index 0000000..9fa2d1c --- /dev/null +++ b/common/core/src/ux_device_stack_class_unregister.c @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_class_unregister PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function unregisters a slave class to the slave stack. */ +/* */ +/* Note: The C string of class_name must be NULL-terminated and the */ +/* length of it (without the NULL-terminator itself) must be no larger */ +/* than UX_MAX_CLASS_NAME_LENGTH. */ +/* */ +/* INPUT */ +/* */ +/* class_name Name of class */ +/* class_function_entry Class entry function */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_string_length_check Check C string and return */ +/* its length if null-terminated */ +/* _ux_utility_memory_compare Memory compare */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_class_unregister(UCHAR *class_name, + UINT (*class_entry_function)(struct UX_SLAVE_CLASS_COMMAND_STRUCT *)) +{ + +UX_SLAVE_CLASS *class; +ULONG class_index; +UINT status; +UX_SLAVE_CLASS_COMMAND command; +UINT class_name_length = 0; + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_CLASS_UNREGISTER, class_name, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the length of the class name (exclude null-terminator). */ + status = _ux_utility_string_length_check(class_name, &class_name_length, UX_MAX_CLASS_NAME_LENGTH); + if (status) + return(status); + + /* We need to parse the class table to find the right class. */ + class = _ux_system_slave -> ux_system_slave_class_array; + for (class_index = 0; class_index < _ux_system_slave -> ux_system_slave_max_class; class_index++) + { + + /* Check if this class is the right one. */ + if (class -> ux_slave_class_status == UX_USED) + { + + /* We have found a used container with a class. Compare the name (include null-terminator). */ + if (_ux_utility_memory_compare(class -> ux_slave_class_name, class_name, class_name_length + 1) == UX_SUCCESS) + { + + /* Build all the fields of the Class Command to uninitialize the class. */ + command.ux_slave_class_command_request = UX_SLAVE_CLASS_COMMAND_UNINITIALIZE; + command.ux_slave_class_command_class_ptr = class; + + /* Call the class uninitialization routine. */ + status = class_entry_function(&command); + + /* Check the status. */ + if (status != UX_SUCCESS) + return(status); + + /* Make this class unused now. */ + class -> ux_slave_class_status = UX_UNUSED; + + /* Erase the instance of the class. */ + class -> ux_slave_class_instance = UX_NULL; + + /* Return successful completion. */ + return(UX_SUCCESS); + } + } + + /* Move to the next class. */ + class++; + } + + /* No class match. */ + return(UX_NO_CLASS_MATCH); +} + diff --git a/common/core/src/ux_device_stack_clear_feature.c b/common/core/src/ux_device_stack_clear_feature.c new file mode 100644 index 0000000..02356d0 --- /dev/null +++ b/common/core/src/ux_device_stack_clear_feature.c @@ -0,0 +1,175 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_clear_feature PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function clears a specific feature (Device, Interface, */ +/* Endpoint ....). */ +/* */ +/* INPUT */ +/* */ +/* request_type Request type */ +/* request_value Request value */ +/* request_index Request index */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* */ +/* CALLED BY */ +/* */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_clear_feature(ULONG request_type, ULONG request_value, ULONG request_index) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_DEVICE *device; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_ENDPOINT *endpoint_target; + + UX_PARAMETER_NOT_USED(request_value); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_CLEAR_FEATURE, request_type, request_value, request_index, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the control endpoint for the device. */ + endpoint = &device -> ux_slave_device_control_endpoint; + + /* The request can be for either the device or the endpoint. */ + switch (request_type & UX_REQUEST_TARGET) + { + + case UX_REQUEST_TARGET_DEVICE: + + /* Check if we have a DEVICE_REMOTE_WAKEUP Feature. */ + if (request_value == UX_REQUEST_FEATURE_DEVICE_REMOTE_WAKEUP) + { + + /* Check if we have the capability. */ + if (_ux_system_slave -> ux_system_slave_remote_wakeup_capability) + { + + /* Disable the feature. */ + _ux_system_slave -> ux_system_slave_remote_wakeup_enabled = UX_FALSE; + } + + else + + /* Protocol error. */ + return (UX_FUNCTION_NOT_SUPPORTED); + } + + break; + + case UX_REQUEST_TARGET_ENDPOINT: + + /* The only clear feature for endpoint is ENDPOINT_STALL. This clears + the endpoint of the stall situation and resets its data toggle. + We need to find the endpoint through the interface(s). */ + interface = device -> ux_slave_device_first_interface; + + while (interface != UX_NULL) + { + + /* Get the first endpoint for this interface. */ + endpoint_target = interface -> ux_slave_interface_first_endpoint; + + /* Parse all the endpoints. */ + while (endpoint_target != UX_NULL) + { + + /* Check the endpoint index. */ + if (endpoint_target -> ux_slave_endpoint_descriptor.bEndpointAddress == request_index) + { + + /* Reset the endpoint. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_RESET_ENDPOINT, endpoint_target); + + /* Mark its state now. */ + endpoint_target -> ux_slave_endpoint_state = UX_ENDPOINT_RESET; + + /* Return the function status. */ + return(UX_SUCCESS); + } + + /* Next endpoint. */ + endpoint_target = endpoint_target -> ux_slave_endpoint_next_endpoint; + } + + /* Next interface. */ + interface = interface -> ux_slave_interface_next_interface; + } + /* Intentional fallthrough and go into the default case. */ + /* fall through */ + + /* We get here when the endpoint is wrong. Should not happen though. */ + default: + + /* We stall the command. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + + /* No more work to do here. The command failed but the upper layer does not depend on it. */ + return(UX_SUCCESS); + } + + /* Return the function status. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_device_stack_configuration_get.c b/common/core/src/ux_device_stack_configuration_get.c new file mode 100644 index 0000000..f069038 --- /dev/null +++ b/common/core/src/ux_device_stack_configuration_get.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_configuration_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the current configuration for the device. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_configuration_get(VOID) +{ + +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UINT status; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the control endpoint for the device. */ + endpoint = &device -> ux_slave_device_control_endpoint; + + /* Get the pointer to the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Set the value of the configuration in the buffer. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = + (UCHAR) device -> ux_slave_device_configuration_selected; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_CONFIGURATION_GET, device -> ux_slave_device_configuration_selected, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Set the phase of the transfer to data out. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* Send the descriptor with the appropriate length to the host. */ + status = _ux_device_stack_transfer_request(transfer_request, 1, 1); + + /* Return the function status. */ + return(status); +} + diff --git a/common/core/src/ux_device_stack_configuration_set.c b/common/core/src/ux_device_stack_configuration_set.c new file mode 100644 index 0000000..6c55218 --- /dev/null +++ b/common/core/src/ux_device_stack_configuration_set.c @@ -0,0 +1,374 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_configuration_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the configuration from the host and will enable */ +/* the default alternate setting 0 for all the interfaces attached to */ +/* this configuration. */ +/* */ +/* INPUT */ +/* */ +/* endpoint Pointer to endpoint */ +/* configuration_value Configuration selected */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_class_entry_function) Device class entry function */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* _ux_device_stack_interface_delete Delete interface */ +/* _ux_device_stack_interface_set Set interface */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_configuration_set(ULONG configuration_value) +{ + +UX_SLAVE_DCD *dcd; +UCHAR * device_framework; +ULONG device_framework_length; +ULONG descriptor_length; +UCHAR descriptor_type; +UX_CONFIGURATION_DESCRIPTOR configuration_descriptor = { 0 }; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_INTERFACE *next_interface; +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS *current_class = UX_NULL; +UX_SLAVE_CLASS_COMMAND class_command; +UX_SLAVE_DEVICE *device; +ULONG iad_flag; +ULONG iad_first_interface = 0; +ULONG iad_number_interfaces = 0; +ULONG class_index; + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_CONFIGURATION_SET, configuration_value, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Reset the IAD flag. */ + iad_flag = UX_FALSE; + + /* If the configuration value is already selected, keep it. */ + if (device -> ux_slave_device_configuration_selected == configuration_value) + return(UX_SUCCESS); + + /* We may have multiple configurations !, the index will tell us what + configuration descriptor we need to return. */ + device_framework = _ux_system_slave -> ux_system_slave_device_framework; + device_framework_length = _ux_system_slave -> ux_system_slave_device_framework_length; + + /* Parse the device framework and locate a configuration descriptor. */ + while (device_framework_length != 0) + { + /* Get the length of the current descriptor. */ + descriptor_length = (ULONG) *device_framework; + + /* And its type. */ + descriptor_type = *(device_framework + 1); + + /* Check if this is a configuration descriptor. */ + if (descriptor_type == UX_CONFIGURATION_DESCRIPTOR_ITEM) + { + /* Parse the descriptor in something more readable. */ + _ux_utility_descriptor_parse(device_framework, + _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, + (UCHAR *) &configuration_descriptor); + + /* Now we need to check the configuration value. It has + to be the same as the one specified in the setup function. */ + if (configuration_descriptor.bConfigurationValue == configuration_value) + /* The configuration is found. */ + break; + } + + /* Adjust what is left of the device framework. */ + device_framework_length -= descriptor_length; + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + + /* Configuration not found. */ + if (device_framework_length == 0 && configuration_value != 0) + return(UX_ERROR); + + /* We unmount the configuration if there is previous configuration selected. */ + if (device -> ux_slave_device_configuration_selected) + { + + /* Get the pointer to the first interface. */ + interface = device -> ux_slave_device_first_interface; + + /* Deactivate all the interfaces if any. */ + while (interface != UX_NULL) + { + + /* Build all the fields of the Class Command. */ + class_command.ux_slave_class_command_request = UX_SLAVE_CLASS_COMMAND_DEACTIVATE; + class_command.ux_slave_class_command_interface = (VOID *) interface; + + /* Get the pointer to the class container of this interface. */ + class = interface -> ux_slave_interface_class; + + /* Store the class container. */ + class_command.ux_slave_class_command_class_ptr = class; + + /* If there is a class container for this instance, deactivate it. */ + if (class != UX_NULL) + + /* Call the class with the DEACTIVATE signal. */ + class -> ux_slave_class_entry_function(&class_command); + + /* Get the next interface. */ + next_interface = interface -> ux_slave_interface_next_interface; + + /* Remove the interface and all endpoints associated with it. */ + _ux_device_stack_interface_delete(interface); + + /* Now we refresh the interface pointer. */ + interface = next_interface; + } + } + + /* No configuration is selected. */ + device -> ux_slave_device_configuration_selected = 0; + + /* Mark the device as attached now. */ + device -> ux_slave_device_state = UX_DEVICE_ATTACHED; + + /* The DCD needs to update the device state too. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_CHANGE_STATE, (VOID *) UX_DEVICE_ATTACHED); + + /* If the host tries to unconfigure, we are done. */ + if (configuration_value == 0) + return(UX_SUCCESS); + + /* Memorize the configuration selected. */ + device -> ux_slave_device_configuration_selected = configuration_value; + + /* We have found the configuration value requested by the host. + Create the configuration descriptor and attach it to the device. */ + _ux_utility_descriptor_parse(device_framework, + _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, + (UCHAR *) &device -> ux_slave_device_configuration_descriptor); + + /* Configuration character D6 is for Self-powered */ + _ux_system_slave -> ux_system_slave_power_state = (configuration_descriptor.bmAttributes & 0x40) ? UX_DEVICE_SELF_POWERED : UX_DEVICE_BUS_POWERED; + + /* Configuration character D5 is for Remote Wakeup */ + _ux_system_slave -> ux_system_slave_remote_wakeup_capability = (configuration_descriptor.bmAttributes & 0x20) ? UX_TRUE : UX_FALSE; + + /* Search only in current configuration */ + device_framework_length = configuration_descriptor.wTotalLength; + + /* We need to scan all the interface descriptors following this + configuration descriptor and enable all endpoints associated + with the default alternate setting of each interface. */ + while (device_framework_length != 0) + { + + /* Get the length of the current descriptor. */ + descriptor_length = (ULONG) *device_framework; + + /* And its type. */ + descriptor_type = *(device_framework + 1); + + /* Check if this is an interface association descriptor. */ + if(descriptor_type == UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ITEM) + { + + /* Set the IAD flag. */ + iad_flag = UX_TRUE; + + /* Get the first interface we have in the IAD. */ + iad_first_interface = (ULONG) *(device_framework + 2); + + /* Get the number of interfaces we have in the IAD. */ + iad_number_interfaces = (ULONG) *(device_framework + 3); + } + + /* Check if this is an interface descriptor. */ + if(descriptor_type == UX_INTERFACE_DESCRIPTOR_ITEM) + { + + /* Parse the descriptor in something more readable. */ + _ux_utility_descriptor_parse(device_framework, + _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, + (UCHAR *) &interface_descriptor); + + /* If the alternate setting is 0 for this interface, we need to + memorize its class association and start it. */ + if (interface_descriptor.bAlternateSetting == 0) + { + + /* Are we in a IAD scenario ? */ + if (iad_flag == UX_TRUE) + { + + /* Check if this is the first interface from the IAD. In this case, + we need to match a class to this interface. */ + if (interface_descriptor.bInterfaceNumber == iad_first_interface) + { + + /* First interface. Scan the list of classes to find a match. */ + class = _ux_system_slave -> ux_system_slave_class_array; + + /* Parse all the class drivers. */ + for (class_index = 0; class_index < _ux_system_slave -> ux_system_slave_max_class; class_index++) + { + + /* Check if this class driver is used. */ + if (class -> ux_slave_class_status == UX_USED) + { + + /* Check if this is the same interface for the same configuration. */ + if ((interface_descriptor.bInterfaceNumber == class -> ux_slave_class_interface_number) && + (configuration_value == class -> ux_slave_class_configuration_number)) + { + + /* Memorize the class in the class/interface array. */ + _ux_system_slave -> ux_system_slave_interface_class_array[interface_descriptor.bInterfaceNumber] = class; + + /* And again as the current class. */ + current_class = class; + + /* We are done here. */ + break; + } + } + + /* Move to the next registered class. */ + class++; + } + } + else + + /* Memorize the class in the class/interface array. We use the current class. */ + _ux_system_slave -> ux_system_slave_interface_class_array[interface_descriptor.bInterfaceNumber] = current_class; + + /* Decrement the number of interfaces found in the same IAD. */ + iad_number_interfaces--; + + /* If none are left, get out of the IAD state machine. */ + if (iad_number_interfaces == 0) + + /* We have exhausted the interfaces within the IAD. */ + iad_flag = UX_FALSE; + + } + else + { + + /* First interface. Scan the list of classes to find a match. */ + class = _ux_system_slave -> ux_system_slave_class_array; + + /* Parse all the class drivers. */ + for (class_index = 0; class_index < _ux_system_slave -> ux_system_slave_max_class; class_index++) + { + + /* Check if this class driver is used. */ + if (class -> ux_slave_class_status == UX_USED) + { + + /* Check if this is the same interface for the same configuration. */ + if ((interface_descriptor.bInterfaceNumber == class -> ux_slave_class_interface_number) && + (configuration_value == class -> ux_slave_class_configuration_number)) + { + + /* Memorize the class in the class/interface array. */ + _ux_system_slave -> ux_system_slave_interface_class_array[interface_descriptor.bInterfaceNumber] = class; + + /* We are done here. */ + break; + } + } + + /* Move to the next registered class. */ + class++; + } + } + + /* Set the interface. */ + _ux_device_stack_interface_set(device_framework, device_framework_length, 0); + } + } + + /* Adjust what is left of the device framework. */ + device_framework_length -= descriptor_length; + + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + + /* Mark the device as configured now. */ + device -> ux_slave_device_state = UX_DEVICE_CONFIGURED; + + /* The DCD needs to update the device state too. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_CHANGE_STATE, (VOID *) UX_DEVICE_CONFIGURED); + + /* Configuration mounted. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_device_stack_control_request_process.c b/common/core/src/ux_device_stack_control_request_process.c new file mode 100644 index 0000000..3fbf671 --- /dev/null +++ b/common/core/src/ux_device_stack_control_request_process.c @@ -0,0 +1,312 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_control_request_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the DCD when the device has received a */ +/* SETUP packet. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_class_entry_function) Device class entry function */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_device_stack_alternate_setting_get */ +/* Get alternate settings */ +/* _ux_device_stack_alternate_setting_set */ +/* Set alternate settings */ +/* _ux_device_stack_clear_feature Clear feature */ +/* _ux_device_stack_configuration_get Get configuration */ +/* _ux_device_stack_configuration_set Set configuration */ +/* _ux_device_stack_descriptor_send Send descriptor */ +/* _ux_device_stack_get_status Get status */ +/* _ux_device_stack_set_feature Set feature */ +/* _ux_utility_short_get Get short value */ +/* */ +/* CALLED BY */ +/* */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_control_request_process(UX_SLAVE_TRANSFER *transfer_request) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_DEVICE *device; +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_COMMAND class_command; +ULONG request_type; +ULONG request; +ULONG request_value; +ULONG request_index; +ULONG request_length; +ULONG class_index; +UINT status = UX_ERROR; +UX_SLAVE_ENDPOINT *endpoint; +ULONG application_data_length; + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Ensure that the Setup request has been received correctly. */ + if (transfer_request -> ux_slave_transfer_request_completion_code == UX_SUCCESS) + { + + /* Seems so far, the Setup request is valid. Extract all fields of + the request. */ + request_type = *transfer_request -> ux_slave_transfer_request_setup; + request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST); + request_value = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE); + request_index = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_INDEX); + request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH); + + /* Filter for GET_DESCRIPTOR/SET_DESCRIPTOR commands. If the descriptor to be returned is not a standard descriptor, + treat the command as a CLASS command. */ + if ((request == UX_GET_DESCRIPTOR || request == UX_SET_DESCRIPTOR) && (((request_value >> 8) & UX_REQUEST_TYPE) != UX_REQUEST_TYPE_STANDARD)) + { + + /* This request is to be handled by the class layer. */ + request_type &= (UINT)~UX_REQUEST_TYPE; + request_type |= UX_REQUEST_TYPE_CLASS; + } + + /* Check if there is a vendor registered function at the application layer. If the request + is VENDOR and the request match, pass the request to the application. */ + if ((request_type & UX_REQUEST_TYPE) == UX_REQUEST_TYPE_VENDOR) + { + + /* Check the request demanded and compare it to the application registered one. */ + if (request == _ux_system_slave -> ux_system_slave_device_vendor_request) + { + + /* This is a Microsoft extended function. It happens before the device is configured. + The request is passed to the application directly. */ + status = _ux_system_slave -> ux_system_slave_device_vendor_request_function(request, request_value, + request_index, request_length, + transfer_request -> ux_slave_transfer_request_data_pointer, + &application_data_length); + + /* Check the status from the application. */ + if (status == UX_SUCCESS) + { + + /* Get the control endpoint associated with the device. */ + endpoint = &device -> ux_slave_device_control_endpoint; + + /* Get the pointer to the transfer request associated with the control endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Set the direction to OUT. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* Perform the data transfer. */ + _ux_device_stack_transfer_request(transfer_request, request_length, application_data_length); + + /* We are done here. */ + return(UX_SUCCESS); + } + else + { + + /* The application did not like the vendor command format, stall the control endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + + /* We are done here. */ + return(UX_SUCCESS); + } + } + } + + /* Check the destination of the request. If the request is of type CLASS or VENDOR_SPECIFIC, + the function has to be passed to the class layer. */ + if (((request_type & UX_REQUEST_TYPE) == UX_REQUEST_TYPE_CLASS) || + ((request_type & UX_REQUEST_TYPE) == UX_REQUEST_TYPE_VENDOR)) + { + + /* Build all the fields of the Class Command. */ + class_command.ux_slave_class_command_request = UX_SLAVE_CLASS_COMMAND_REQUEST; + + /* We need to find which class this request is for. */ + for (class_index = 0; class_index < UX_MAX_SLAVE_INTERFACES; class_index ++) + { + + /* Is the request target to an interface? */ + if ((request_type & UX_REQUEST_TARGET) == UX_REQUEST_TARGET_INTERFACE) + { + + /* Yes, so the request index contains the index of the interface + the request is for. So if the current index does not match + the request index, we should go to the next one. */ + if ((request_index & 0xFF) != class_index) + continue; + } + + /* Get the class for the interface. */ + class = _ux_system_slave -> ux_system_slave_interface_class_array[class_index]; + + /* If class is not ready, try next. */ + if (class == UX_NULL) + continue; + + /* Memorize the class in the command. */ + class_command.ux_slave_class_command_class_ptr = class; + + /* We have found a potential candidate. Call this registered class entry function. */ + status = class -> ux_slave_class_entry_function(&class_command); + + /* The status simply tells us if the registered class handled the + command - if there was an issue processing the command, it would've + stalled the control endpoint, notifying the host (and not us). */ + if (status == UX_SUCCESS) + + /* We are done, break the loop! */ + break; + + /* Not handled, try next. */ + } + + /* If no class handled the command, then we have an error here. */ + if (status != UX_SUCCESS) + + /* We stall the command (request not supported). */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + + /* We are done for class/vendor request. */ + return(status); + } + + /* At this point, the request must be a standard request that the device stack should handle. */ + switch (request) + { + + case UX_GET_STATUS: + + status = _ux_device_stack_get_status(request_type, request_index, request_length); + break; + + case UX_CLEAR_FEATURE: + + status = _ux_device_stack_clear_feature(request_type, request_value, request_index); + break; + + case UX_SET_FEATURE: + + status = _ux_device_stack_set_feature(request_type, request_value, request_index); + break; + + case UX_SET_ADDRESS: + + /* Memorize the address. Some controllers memorize the address here. Some don't. */ + dcd -> ux_slave_dcd_device_address = request_value; + + /* Force the new address. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_SET_DEVICE_ADDRESS, (VOID *) (ALIGN_TYPE) request_value); + break; + + case UX_GET_DESCRIPTOR: + + status = _ux_device_stack_descriptor_send(request_value, request_index, request_length); + break; + + case UX_SET_DESCRIPTOR: + + status = UX_FUNCTION_NOT_SUPPORTED; + break; + + case UX_GET_CONFIGURATION: + + status = _ux_device_stack_configuration_get(); + break; + + case UX_SET_CONFIGURATION: + + status = _ux_device_stack_configuration_set(request_value); + break; + + case UX_GET_INTERFACE: + + status = _ux_device_stack_alternate_setting_get(request_index); + break; + + case UX_SET_INTERFACE: + + status = _ux_device_stack_alternate_setting_set(request_index,request_value); + break; + + + case UX_SYNCH_FRAME: + + status = UX_SUCCESS; + break; + + default : + + status = UX_FUNCTION_NOT_SUPPORTED; + break; + } + + if (status != UX_SUCCESS) + + /* Stall the control endpoint to issue protocol error. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + } + + /* Return the function status. */ + return(status); +} + diff --git a/common/core/src/ux_device_stack_descriptor_send.c b/common/core/src/ux_device_stack_descriptor_send.c new file mode 100644 index 0000000..a1906fb --- /dev/null +++ b/common/core/src/ux_device_stack_descriptor_send.c @@ -0,0 +1,544 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_descriptor_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends back the device descriptor required by the host.*/ +/* */ +/* INPUT */ +/* */ +/* descriptor_type Descriptor type */ +/* descriptor_index Index of descriptor */ +/* host_length Length requested by host */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* _ux_device_stack_transfer_request Process transfer request */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_utility_memory_copy Memory copy */ +/* _ux_utility_short_get Get short value */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_descriptor_send(ULONG descriptor_type, ULONG request_index, ULONG host_length) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_DEVICE *device; +ULONG descriptor_index; +ULONG parsed_descriptor_index; +UX_SLAVE_TRANSFER *transfer_request; +UX_CONFIGURATION_DESCRIPTOR configuration_descriptor; +UX_SLAVE_ENDPOINT *endpoint; +UCHAR *device_framework; +UCHAR *device_framework_end; +ULONG device_framework_length; +ULONG descriptor_length; +ULONG configuration_descriptor_length; +UINT status = UX_ERROR; +ULONG length; +UCHAR *string_memory; +UCHAR *string_framework; +ULONG string_framework_length; +ULONG string_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_DESCRIPTOR_SEND, descriptor_type, request_index, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the control endpoint associated with the device. */ + endpoint = &device -> ux_slave_device_control_endpoint; + + /* Get the pointer to the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Set the direction to OUT. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* Isolate the descriptor index. */ + descriptor_index = descriptor_type & 0xff; + + /* Reset the parsed index. */ + parsed_descriptor_index = 0; + + /* Shift the descriptor type in the low byte field. */ + descriptor_type = (UCHAR) ((descriptor_type >> 8) & 0xff); + + /* What type of descriptor do we need to return? */ + switch (descriptor_type) + { + + case UX_DEVICE_DESCRIPTOR_ITEM: + + /* Setup the length appropriately. */ + if (host_length > UX_DEVICE_DESCRIPTOR_LENGTH) + length = UX_DEVICE_DESCRIPTOR_LENGTH; + else + length = host_length; + + /* Copy the device descriptor into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + _ux_system_slave -> ux_system_slave_device_framework, length); + + /* Perform the data transfer. */ + status = _ux_device_stack_transfer_request(transfer_request, length, host_length); + break; + + case UX_DEVICE_QUALIFIER_DESCRIPTOR_ITEM: + + /* Setup the length appropriately. */ + if (host_length > UX_DEVICE_QUALIFIER_DESCRIPTOR_LENGTH) + length = UX_DEVICE_QUALIFIER_DESCRIPTOR_LENGTH; + else + length = host_length; + + /* We may or may not have a device qualifier descriptor. */ + device_framework = _ux_system_slave -> ux_system_slave_device_framework; + device_framework_length = _ux_system_slave -> ux_system_slave_device_framework_length; + device_framework_end = device_framework + device_framework_length; + + /* Parse the device framework and locate a device qualifier descriptor. */ + while (device_framework < device_framework_end) + { + + /* Get the type of the current descriptor. */ + descriptor_type = *(device_framework + 1); + + /* And its length. */ + descriptor_length = (ULONG) *device_framework; + + /* Check if this is a device qualifier descriptor. */ + if (descriptor_type == UX_DEVICE_QUALIFIER_DESCRIPTOR_ITEM) + { + + /* Copy the device qualifier descriptor into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + device_framework, length); + + /* Perform the data transfer. */ + status = _ux_device_stack_transfer_request(transfer_request, length, host_length); + break; + } + + /* Adjust what is left of the device framework. */ + device_framework_length -= descriptor_length; + + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + + break; + + case UX_OTG_DESCRIPTOR_ITEM: + + /* Setup the length appropriately. */ + if (host_length > UX_OTG_DESCRIPTOR_LENGTH) + length = UX_OTG_DESCRIPTOR_LENGTH; + else + length = host_length; + + /* We may or may not have a OTG descriptor. */ + device_framework = _ux_system_slave -> ux_system_slave_device_framework; + device_framework_length = _ux_system_slave -> ux_system_slave_device_framework_length; + device_framework_end = device_framework + device_framework_length; + + /* Parse the device framework and locate a OTG descriptor. */ + while (device_framework < device_framework_end) + { + + /* Get the type of the current descriptor. */ + descriptor_type = *(device_framework + 1); + + /* And its length. */ + descriptor_length = (ULONG) *device_framework; + + /* Check if this is a OTG descriptor. */ + if (descriptor_type == UX_OTG_DESCRIPTOR_ITEM) + { + + /* Copy the device OTG descriptor into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + device_framework, length); + + /* Perform the data transfer. */ + status = _ux_device_stack_transfer_request(transfer_request, length, host_length); + break; + } + + /* Adjust what is left of the device framework. */ + device_framework_length -= descriptor_length; + + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + break; + + case UX_OTHER_SPEED_DESCRIPTOR_ITEM: + + /* This request is used by the host to find out the capability of this device + if it was running at full speed. The behavior is the same as in a GET_CONFIGURATIOn descriptor + but we do not use the current device framework but rather the full speed framework. */ + device_framework = _ux_system_slave -> ux_system_slave_device_framework_full_speed; + device_framework_length = _ux_system_slave -> ux_system_slave_device_framework_length_full_speed; + device_framework_end = device_framework + device_framework_length; + + /* Parse the device framework and locate a configuration descriptor. */ + while (device_framework < device_framework_end) + { + + /* Get the type of the current descriptor. */ + descriptor_type = *(device_framework + 1); + + /* And its length. */ + descriptor_length = (ULONG) *device_framework; + + /* Check if this is a configuration descriptor. We are cheating here. Instead of creating + a OTHER SPEED descriptor, we simply scan the configuration descriptor for the Full Speed + framework and return this configuration after we manually changed the configuration descriptor + item into a Other Speed Descriptor. */ + if (descriptor_type == UX_CONFIGURATION_DESCRIPTOR_ITEM) + { + + /* Check the index. It must be the same as the one requested. */ + if (parsed_descriptor_index == descriptor_index) + { + + /* Parse the configuration descriptor. */ + _ux_utility_descriptor_parse(device_framework, + _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, + (UCHAR *) &configuration_descriptor); + + /* Get the length of entire configuration descriptor. */ + configuration_descriptor_length = configuration_descriptor.wTotalLength; + + /* Ensure the host does not demand a length beyond our descriptor (Windows does that) + and do not return more than what is allowed. */ + if (configuration_descriptor_length < host_length) + length = configuration_descriptor_length; + else + length = host_length; + + /* Check buffer length, since total descriptors length may exceed buffer... */ + if (length > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH) + { + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_DEVICE_STACK, UX_MEMORY_INSUFFICIENT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Stall the endpoint. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + break; + } + + /* Copy the device descriptor into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + device_framework, length); + + /* Now we need to hack the found descriptor because this request expect a OTHER_SPEED + descriptor instead of the regular CONFIGURATION descriptor. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + 1) = UX_OTHER_SPEED_DESCRIPTOR_ITEM; + + /* We can return the configuration descriptor. */ + status = _ux_device_stack_transfer_request(transfer_request, length, host_length); + break; + } + else + { + + /* There may be more configuration descriptors in this framework. */ + parsed_descriptor_index++; + } + } + + /* Adjust what is left of the device framework. */ + device_framework_length -= descriptor_length; + + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + break; + + case UX_CONFIGURATION_DESCRIPTOR_ITEM: + + /* We may have multiple configurations !, the index will tell us what + configuration descriptor we need to return. */ + device_framework = _ux_system_slave -> ux_system_slave_device_framework; + device_framework_length = _ux_system_slave -> ux_system_slave_device_framework_length; + device_framework_end = device_framework + device_framework_length; + + /* Parse the device framework and locate a configuration descriptor. */ + while (device_framework < device_framework_end) + { + + /* Get the type of the current descriptor. */ + descriptor_type = *(device_framework + 1); + + /* And its length. */ + descriptor_length = (ULONG) *device_framework; + + /* Check if this is a configuration descriptor. */ + if (descriptor_type == UX_CONFIGURATION_DESCRIPTOR_ITEM) + { + + /* Check the index. It must be the same as the one requested. */ + if (parsed_descriptor_index == descriptor_index) + { + + /* Parse the configuration descriptor. */ + _ux_utility_descriptor_parse(device_framework, + _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, + (UCHAR *) &configuration_descriptor); + + /* Get the length of entire configuration descriptor. */ + configuration_descriptor_length = configuration_descriptor.wTotalLength; + + /* Ensure the host does not demand a length beyond our descriptor (Windows does that) + and do not return more than what is allowed. */ + if (configuration_descriptor_length < host_length) + length = configuration_descriptor_length; + else + length = host_length; + + /* Check buffer length, since total descriptors length may exceed buffer... */ + if (length > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH) + { + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_DEVICE_STACK, UX_MEMORY_INSUFFICIENT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Stall the endpoint. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + break; + } + + /* Copy the device descriptor into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + device_framework, length); + + /* We can return the configuration descriptor. */ + status = _ux_device_stack_transfer_request(transfer_request, length, host_length); + break; + } + else + { + + /* There may be more configuration descriptors in this framework. */ + parsed_descriptor_index++; + } + } + + /* Adjust what is left of the device framework. */ + device_framework_length -= descriptor_length; + + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + break; + + case UX_STRING_DESCRIPTOR_ITEM: + + /* We need to filter for the index 0 which is the language ID string. */ + if (descriptor_index == 0) + { + + /* We need to check request buffer size in case it's possible exceed. */ + if (_ux_system_slave -> ux_system_slave_language_id_framework_length + 2 > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_DEVICE_STACK, UX_MEMORY_INSUFFICIENT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Stall the endpoint. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + break; + } + + /* We have a request to send back the language ID list. Use the transfer request buffer. */ + string_memory = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Store the total length of the response. */ + *string_memory = (UCHAR)(_ux_system_slave -> ux_system_slave_language_id_framework_length + 2); + + /* Store the descriptor type. */ + *(string_memory +1) = UX_STRING_DESCRIPTOR_ITEM; + + /* Store the language ID into the buffer. */ + _ux_utility_memory_copy(string_memory+2, _ux_system_slave -> ux_system_slave_language_id_framework, + _ux_system_slave -> ux_system_slave_language_id_framework_length); + + /* Filter the length asked/required. */ + if (host_length > _ux_system_slave -> ux_system_slave_language_id_framework_length + 2) + length = _ux_system_slave -> ux_system_slave_language_id_framework_length + 2; + else + length = host_length; + + /* We can return the string language ID descriptor. */ + status = _ux_device_stack_transfer_request(transfer_request, length, host_length); + } + else + { + + /* The host wants a specific string index returned. Get the string framework pointer + and length. */ + string_framework = _ux_system_slave -> ux_system_slave_string_framework; + string_framework_length = _ux_system_slave -> ux_system_slave_string_framework_length; + + /* We search through the string framework until we find the right index. + The index is in the lower byte of the descriptor type. */ + while (string_framework_length != 0) + { + + /* Ensure we have the correct language page. */ + if (_ux_utility_short_get(string_framework) == request_index) + { + + /* Check the index. */ + if (*(string_framework + 2) == descriptor_index) + { + + /* We need to check request buffer size in case it's possible exceed. */ + if (((*(string_framework + 3)*2) + 2) > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_DEVICE_STACK, UX_MEMORY_INSUFFICIENT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Stall the endpoint. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + break; + } + + /* We have a request to send back a string. Use the transfer request buffer. */ + string_memory = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Store the length in the string buffer. The length + of the string descriptor is stored in the third byte, + hence the ' + 3'. The encoding must be in 16-bit + unicode, hence the '*2'. The length includes the size + of the length itself as well as the descriptor type, + hence the ' + 2'. */ + *string_memory = (UCHAR)((*(string_framework + 3)*2) + 2); + + /* Store the Descriptor type. */ + *(string_memory + 1) = UX_STRING_DESCRIPTOR_ITEM; + + /* Create the Unicode string. */ + for (string_length = 0; string_length < *(string_framework + 3) ; string_length ++) + { + + /* Insert a Unicode byte. */ + *(string_memory + 2 + (string_length * 2)) = *(string_framework + 4 + string_length); + + /* Insert a zero after the Unicode byte. */ + *(string_memory + 2 + (string_length * 2) + 1) = 0; + } + + /* Filter the length asked/required. */ + if (host_length > (UINT)((*(string_framework + 3)*2) + 2)) + length = (ULONG)((*(string_framework + 3)*2) + 2); + else + length = host_length; + + /* We can return the string descriptor. */ + status = _ux_device_stack_transfer_request(transfer_request, length, host_length); + break; + } + } + + /* This is the wrong string descriptor, jump to the next. */ + string_framework_length -= (ULONG) *(string_framework + 3) + 4; + string_framework += (ULONG) *(string_framework + 3) + 4; + } + + /* Have we exhausted all the string descriptors? */ + if (string_framework_length == 0) + { + + /* Could not find the required string index. Stall the endpoint. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + return(UX_ERROR); + } + } + break; + + default: + + /* Stall the endpoint. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + return(UX_ERROR); + } + + /* Return the status to the caller. */ + return(status); +} + diff --git a/common/core/src/ux_device_stack_disconnect.c b/common/core/src/ux_device_stack_disconnect.c new file mode 100644 index 0000000..bb2586d --- /dev/null +++ b/common/core/src/ux_device_stack_disconnect.c @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_disconnect PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when the device gets disconnected from the */ +/* host. All the device resources are freed. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_class_entry_function) Device class entry function */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* _ux_device_stack_interface_delete Delete interface */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_disconnect(VOID) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_DEVICE *device; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_INTERFACE *next_interface; +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_COMMAND class_command; +UINT status = UX_ERROR; + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_DISCONNECT, device, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(device); + + /* If the device was in the configured state, there may be interfaces + attached to the configuration. */ + if (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + /* Get the pointer to the first interface. */ + interface = device -> ux_slave_device_first_interface; + + /* Parse all the interfaces if any. */ + while (interface != UX_NULL) + { + + /* Build all the fields of the Class Command. */ + class_command.ux_slave_class_command_request = UX_SLAVE_CLASS_COMMAND_DEACTIVATE; + class_command.ux_slave_class_command_interface = (VOID *) interface; + + /* Get the pointer to the class container of this interface. */ + class = interface -> ux_slave_interface_class; + + /* Store the class container. */ + class_command.ux_slave_class_command_class_ptr = class; + + /* If there is a class container for this instance, deactivate it. */ + if (class != UX_NULL) + + /* Call the class with the DEACTIVATE signal. */ + class -> ux_slave_class_entry_function(&class_command); + + /* Get the next interface. */ + next_interface = interface -> ux_slave_interface_next_interface; + + /* Remove the interface and all endpoints associated with it. */ + _ux_device_stack_interface_delete(interface); + + /* Now we refresh the interface pointer. */ + interface = next_interface; + } + + /* Mark the device as attached now. */ + device -> ux_slave_device_state = UX_DEVICE_ATTACHED; + } + + /* If the device was attached, we need to destroy the control endpoint. */ + if (device -> ux_slave_device_state == UX_DEVICE_ATTACHED) + + /* Now we can destroy the default control endpoint. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_DESTROY_ENDPOINT, + (VOID *) &device -> ux_slave_device_control_endpoint); + + /* We are reverting to configuration 0. */ + device -> ux_slave_device_configuration_selected = 0; + + /* Set the device to be non attached. */ + device -> ux_slave_device_state = UX_DEVICE_RESET; + + /* Check the status change callback. */ + if(_ux_system_slave -> ux_system_slave_change_function != UX_NULL) + { + + /* Inform the application if a callback function was programmed. */ + _ux_system_slave -> ux_system_slave_change_function(UX_DEVICE_REMOVED); + } + + /* Return the status to the caller. */ + return(status); +} + diff --git a/common/core/src/ux_device_stack_endpoint_stall.c b/common/core/src/ux_device_stack_endpoint_stall.c new file mode 100644 index 0000000..53127aa --- /dev/null +++ b/common/core/src/ux_device_stack_endpoint_stall.c @@ -0,0 +1,110 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_endpoint_stall PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function stalls an endpoint. The host will need to reissue */ +/* a reset to clear the endpoint. */ +/* */ +/* INPUT */ +/* */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_endpoint_stall(UX_SLAVE_ENDPOINT *endpoint) +{ + +TX_INTERRUPT_SAVE_AREA + +UX_SLAVE_DCD *dcd; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_ENDPOINT_STALL, endpoint, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Assume device is in an invalid state here in order to reduce code in following + section where interrupts are disabled. */ + status = UX_ERROR; + + /* Ensure we don't change the endpoint's state after disconnection routine + resets it. */ + TX_DISABLE + + /* Check if the device is in a valid state; as soon as the device is out + of the RESET state, transfers occur and thus endpoints may be stalled. */ + if (_ux_system_slave -> ux_system_slave_device.ux_slave_device_state != UX_DEVICE_RESET) + { + + /* Stall the endpoint. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + + /* Mark the endpoint state. */ + endpoint -> ux_slave_endpoint_state = UX_ENDPOINT_HALTED; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_device_stack_get_status.c b/common/core/src/ux_device_stack_get_status.c new file mode 100644 index 0000000..1a14d9e --- /dev/null +++ b/common/core/src/ux_device_stack_get_status.c @@ -0,0 +1,184 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_get_status PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the status of a USB component of the device */ +/* such as device or endpoint. */ +/* */ +/* INPUT */ +/* */ +/* request_type Request type */ +/* request_index Request index */ +/* request_length Request length */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* */ +/* CALLED BY */ +/* */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_get_status(ULONG request_type, ULONG request_index, ULONG request_length) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UINT status; +ULONG data_length; + + UX_PARAMETER_NOT_USED(request_length); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_GET_STATUS, request_type, request_index, request_length, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the control endpoint for the device. */ + endpoint = &device -> ux_slave_device_control_endpoint; + + /* Get the pointer to the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Reset the status buffer. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + 1) = 0; + + /* The default length for GET_STATUS is 2, except for OTG get Status. */ + data_length = 2; + + /* The status can be for either the device or the endpoint. */ + switch (request_type & UX_REQUEST_TARGET) + { + + case UX_REQUEST_TARGET_DEVICE: + + /* When the device is probed, it is either for the power/remote capabilities or OTG role swap. + We differentiate with the Windex, 0 or OTG status Selector. */ + if (request_index == UX_OTG_STATUS_SELECTOR) + { + + /* Set the data length to 1. */ + data_length = 1; + +#ifdef UX_OTG_SUPPORT + /* Store the Role Swap flag. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_otg -> ux_system_otg_slave_role_swap_flag; +#endif + + } + else + { + + /* Store the current power state in the status buffer. */ + if (_ux_system_slave -> ux_system_slave_power_state == UX_DEVICE_SELF_POWERED) + *transfer_request -> ux_slave_transfer_request_data_pointer = 1; + + /* Store the remote wakeup capability state in the status buffer. */ + + if (_ux_system_slave -> ux_system_slave_remote_wakeup_enabled) + *transfer_request -> ux_slave_transfer_request_data_pointer |= 2; + } + + break; + + case UX_REQUEST_TARGET_ENDPOINT: + + /* This feature returns the halt state of a specific endpoint. The endpoint index + is used to retrieve the endpoint container. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_ENDPOINT_STATUS, (VOID *)(ALIGN_TYPE)(request_index & (UINT)~UX_ENDPOINT_DIRECTION)); + + /* Check the status. We may have a unknown endpoint. */ + if (status != UX_ERROR) + { + + if (status == UX_TRUE) + *transfer_request -> ux_slave_transfer_request_data_pointer = 1; + } + else + { + + /* We stall the command. Endpoint is wrong. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + + /* No more work to do here. The command failed but the upper layer does not depend on it. */ + return(UX_SUCCESS); + } + break; + + default: + + /* We stall the command. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + + /* No more work to do here. The command failed but the upper layer does not depend on it. */ + return(UX_SUCCESS); + } + + /* Set the phase of the transfer to data out. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* Send the descriptor with the appropriate length to the host. */ + status = _ux_device_stack_transfer_request(transfer_request, data_length, data_length); + + /* Return the function status. */ + return(status); +} + diff --git a/common/core/src/ux_device_stack_host_wakeup.c b/common/core/src/ux_device_stack_host_wakeup.c new file mode 100644 index 0000000..b10d85e --- /dev/null +++ b/common/core/src/ux_device_stack_host_wakeup.c @@ -0,0 +1,91 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_host_wakeup PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when the device wants to wake up the host. */ +/* This command is only valid when the device is in suspend mode. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_host_wakeup(VOID) +{ + +UX_SLAVE_DCD *dcd; +UINT status = UX_FUNCTION_NOT_SUPPORTED; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_HOST_WAKEUP, 0, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Check if DEVICE_REMOTE_WAKEUP feature is enabled. */ + if (_ux_system_slave -> ux_system_slave_remote_wakeup_enabled) + + /* Send the change signal to the controller driver. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_CHANGE_STATE, (VOID *) UX_DEVICE_REMOTE_WAKEUP); + + /* Return the status to the caller. */ + return(status); +} + diff --git a/common/core/src/ux_device_stack_initialize.c b/common/core/src/ux_device_stack_initialize.c new file mode 100644 index 0000000..4b9ca52 --- /dev/null +++ b/common/core/src/ux_device_stack_initialize.c @@ -0,0 +1,414 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + +UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_SLAVE_CLASS), UX_MAX_SLAVE_CLASS_DRIVER), UX_MAX_SLAVE_CLASS_DRIVER_mul_ovf) + +/* Define the names of all the USB Classes of USBX. */ + +UCHAR _ux_system_slave_class_storage_name[] = "ux_slave_class_storage"; +UCHAR _ux_system_slave_class_cdc_acm_name[] = "ux_slave_class_cdc_acm"; +UCHAR _ux_system_slave_class_dpump_name[] = "ux_slave_class_dpump"; +UCHAR _ux_system_slave_class_pima_name[] = "ux_slave_class_pima"; +UCHAR _ux_system_slave_class_hid_name[] = "ux_slave_class_hid"; +UCHAR _ux_system_slave_class_rndis_name[] = "ux_slave_class_rndis"; +UCHAR _ux_system_slave_class_cdc_ecm_name[] = "ux_slave_class_cdc_ecm"; +UCHAR _ux_system_slave_class_dfu_name[] = "ux_slave_class_dfu"; +UCHAR _ux_system_slave_class_audio_name[] = "ux_slave_class_audio"; + +/* Define USBX Host variable. */ +UX_SYSTEM_SLAVE *_ux_system_slave; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the generic portion of the device side of */ +/* USBX. */ +/* */ +/* INPUT */ +/* */ +/* device_framework_high_speed Pointer to high speed FW */ +/* device_framework_length_high_speed Length of high speed FW */ +/* device_framework_full_speed Pointer to full speed FW */ +/* device_framework_length_full_speed Length of full speed FW */ +/* string_framework Pointer to string FW */ +/* string_framework_length Length of string FW */ +/* language_id_framework Pointer to language ID FW */ +/* language_id_framework_length Length of language ID FW */ +/* (ux_system_slave_change_function) Pointer to callback function */ +/* for device changes */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_initialize(UCHAR * device_framework_high_speed, ULONG device_framework_length_high_speed, + UCHAR * device_framework_full_speed, ULONG device_framework_length_full_speed, + UCHAR * string_framework, ULONG string_framework_length, + UCHAR * language_id_framework, ULONG language_id_framework_length, + UINT (*ux_system_slave_change_function)(ULONG)) +{ +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoints_pool; +UX_SLAVE_INTERFACE *interfaces_pool; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; +ULONG interfaces_found; +ULONG local_interfaces_found; +ULONG endpoints_found; +ULONG local_endpoints_found; +ULONG endpoints_in_interface_found; +UCHAR *device_framework; +ULONG device_framework_length; +UCHAR descriptor_type; +ULONG descriptor_length; +UCHAR *memory; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_INITIALIZE, 0, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Store the high speed device framework address and length in the project structure. */ + _ux_system_slave -> ux_system_slave_device_framework_high_speed = device_framework_high_speed; + _ux_system_slave -> ux_system_slave_device_framework_length_high_speed = device_framework_length_high_speed; + + /* Store the string framework address and length in the project structure. */ + _ux_system_slave -> ux_system_slave_device_framework_full_speed = device_framework_full_speed; + _ux_system_slave -> ux_system_slave_device_framework_length_full_speed = device_framework_length_full_speed; + + /* Store the string framework address and length in the project structure. */ + _ux_system_slave -> ux_system_slave_string_framework = string_framework; + _ux_system_slave -> ux_system_slave_string_framework_length = string_framework_length; + + /* Store the language ID list in the project structure. */ + _ux_system_slave -> ux_system_slave_language_id_framework = language_id_framework; + _ux_system_slave -> ux_system_slave_language_id_framework_length = language_id_framework_length; + + /* Store the max number of slave class drivers in the project structure. */ + _ux_system_slave -> ux_system_slave_max_class = UX_MAX_SLAVE_CLASS_DRIVER; + + /* Store the device state change function callback. */ + _ux_system_slave -> ux_system_slave_change_function = ux_system_slave_change_function; + + /* Allocate memory for the classes. + * sizeof(UX_SLAVE_CLASS) * UX_MAX_SLAVE_CLASS_DRIVER) overflow is checked + * outside of the function. + */ + memory = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS) * UX_MAX_SLAVE_CLASS_DRIVER); + if (memory == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save this memory allocation in the USBX project. */ + _ux_system_slave -> ux_system_slave_class_array = (UX_SLAVE_CLASS *) ((void *) memory); + + /* Allocate some memory for the Control Endpoint. First get the address of the transfer request for the + control endpoint. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Acquire a buffer for the size of the endpoint. */ + transfer_request -> ux_slave_transfer_request_data_pointer = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH); + + /* Ensure we have enough memory. */ + if (transfer_request -> ux_slave_transfer_request_data_pointer == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + else + status = UX_SUCCESS; + + /* Reset all values we are using during the scanning of the framework. */ + interfaces_found = 0; + endpoints_found = 0; + + /* Go on to scan interfaces if no error. */ + if (status == UX_SUCCESS) + { + + /* We need to determine the maximum number of interfaces and endpoints declared in the device framework. + This mechanism requires that both framework behave the same way regarding the number of interfaces + and endpoints. */ + device_framework = _ux_system_slave -> ux_system_slave_device_framework_full_speed; + device_framework_length = _ux_system_slave -> ux_system_slave_device_framework_length_full_speed; + + /* Reset all values we are using during the scanning of the framework. */ + local_interfaces_found = 0; + local_endpoints_found = 0; + endpoints_in_interface_found = 0; + + /* Parse the device framework and locate interfaces and endpoint descriptor(s). */ + while (device_framework_length != 0) + { + + /* Get the length of this descriptor. */ + descriptor_length = (ULONG) *device_framework; + + /* And its type. */ + descriptor_type = *(device_framework + 1); + + /* Check if this is an endpoint descriptor. */ + switch(descriptor_type) + { + + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Check if this is alternate setting 0. If not, do not add another interface found. + If this is alternate setting 0, reset the endpoints count for this interface. */ + if (*(device_framework + 3) == 0) + { + + /* Add the cumulated number of endpoints in the previous interface. */ + local_endpoints_found += endpoints_in_interface_found; + + /* Read the number of endpoints for this alternate setting. */ + endpoints_in_interface_found = (ULONG) *(device_framework + 4); + + /* Increment the number of interfaces found in the current configuration. */ + local_interfaces_found++; + } + else + { + + /* Compare the number of endpoints found in this non 0 alternate setting. */ + if (endpoints_in_interface_found < (ULONG) *(device_framework + 4)) + + /* Adjust the number of maximum endpoints in this interface. */ + endpoints_in_interface_found = (ULONG) *(device_framework + 4); + } + + break; + + case UX_CONFIGURATION_DESCRIPTOR_ITEM: + + /* Check if the number of interfaces found in this configuration is the maximum so far. */ + if (local_interfaces_found > interfaces_found) + + /* We need to adjust the number of maximum interfaces. */ + interfaces_found = local_interfaces_found; + + /* We have a new configuration. We need to reset the number of local interfaces. */ + local_interfaces_found = 0; + + /* Add the cumulated number of endpoints in the previous interface. */ + local_endpoints_found += endpoints_in_interface_found; + + /* Check if the number of endpoints found in the previous configuration is the maximum so far. */ + if (local_endpoints_found > endpoints_found) + + /* We need to adjust the number of maximum endpoints. */ + endpoints_found = local_endpoints_found; + + /* We have a new configuration. We need to reset the number of local endpoints. */ + local_endpoints_found = 0; + endpoints_in_interface_found = 0; + + break; + + default: + break; + } + + /* Adjust what is left of the device framework. */ + device_framework_length -= descriptor_length; + + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + + /* Add the cumulated number of endpoints in the previous interface. */ + local_endpoints_found += endpoints_in_interface_found; + + /* Check if the number of endpoints found in the previous interface is the maximum so far. */ + if (local_endpoints_found > endpoints_found) + + /* We need to adjust the number of maximum endpoints. */ + endpoints_found = local_endpoints_found; + + + /* Check if the number of interfaces found in this configuration is the maximum so far. */ + if (local_interfaces_found > interfaces_found) + + /* We need to adjust the number of maximum interfaces. */ + interfaces_found = local_interfaces_found; + + /* We do a sanity check on the finding. At least there must be one interface but endpoints are + not necessary. */ + if (interfaces_found == 0) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_INIT, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, device_framework, 0, 0, UX_TRACE_ERRORS, 0, 0) + + status = UX_DESCRIPTOR_CORRUPTED; + } + } + + /* Go on to allocate endpoints pool if no error. */ + if (status == UX_SUCCESS) + { + + /* Memorize both pool sizes. */ + device -> ux_slave_device_interfaces_pool_number = interfaces_found; + device -> ux_slave_device_endpoints_pool_number = endpoints_found; + + /* We assign a pool for the interfaces. */ + interfaces_pool = _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, interfaces_found, sizeof(UX_SLAVE_INTERFACE)); + if (interfaces_pool == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + else + + /* Save the interface pool address in the device container. */ + device -> ux_slave_device_interfaces_pool = interfaces_pool; + } + + /* Do we need an endpoint pool ? */ + if (endpoints_found != 0 && status == UX_SUCCESS) + { + + /* We assign a pool for the endpoints. */ + endpoints_pool = _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, endpoints_found, sizeof(UX_SLAVE_ENDPOINT)); + if (endpoints_pool == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + else + { + + /* Save the endpoint pool address in the device container. */ + device -> ux_slave_device_endpoints_pool = endpoints_pool; + + /* We need to assign a transfer buffer to each endpoint. Each endpoint is assigned the + maximum buffer size. We also assign the semaphore used by the endpoint to synchronize transfer + completion. */ + while (endpoints_pool < (device -> ux_slave_device_endpoints_pool + endpoints_found)) + { + + /* Obtain some memory. */ + endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + + /* Ensure we could allocate memory. */ + if (endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer == UX_NULL) + { + status = UX_MEMORY_INSUFFICIENT; + break; + } + + /* Create the semaphore for the endpoint. */ + status = _ux_utility_semaphore_create(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore, + "ux_transfer_request_semaphore", 0); + + /* Check completion status. */ + if (status != UX_SUCCESS) + { + status = UX_SEMAPHORE_ERROR; + break; + } + + /* Next endpoint. */ + endpoints_pool++; + } + } + } + else + endpoints_pool = UX_NULL; + + /* Return successful completion. */ + if (status == UX_SUCCESS) + return(UX_SUCCESS); + + /* Free resources when there is error. */ + + /* Free device -> ux_slave_device_endpoints_pool. */ + if (endpoints_pool) + { + + /* In error cases creating endpoint resources, endpoints_pool is endpoint that failed. + * Previously allocated things should be freed. */ + while(endpoints_pool >= device -> ux_slave_device_endpoints_pool) + { + + /* Delete ux_slave_transfer_request_semaphore. */ + if (endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore.tx_semaphore_id != 0) + _ux_utility_semaphore_delete(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore); + + /* Free ux_slave_transfer_request_data_pointer buffer. */ + if (endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer) + _ux_utility_memory_free(endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer); + + /* Move to previous endpoint. */ + endpoints_pool --; + } + + _ux_utility_memory_free(device -> ux_slave_device_endpoints_pool); + } + + /* Free device -> ux_slave_device_interfaces_pool. */ + if (device -> ux_slave_device_interfaces_pool) + _ux_utility_memory_free(device -> ux_slave_device_interfaces_pool); + + /* Free device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer. */ + if (device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer) + _ux_utility_memory_free(device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer); + + /* Free _ux_system_slave -> ux_system_slave_class_array. */ + _ux_utility_memory_free(_ux_system_slave -> ux_system_slave_class_array); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_device_stack_interface_delete.c b/common/core/src/ux_device_stack_interface_delete.c new file mode 100644 index 0000000..9d8ca4e --- /dev/null +++ b/common/core/src/ux_device_stack_interface_delete.c @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_interface_delete PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes an interface. Semaphore and memory are */ +/* released and the controller driver is invoked to disable the */ +/* hardware endpoint. The interface is then removed from the */ +/* configuration. */ +/* */ +/* INPUT */ +/* */ +/* interface Pointer to interface */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_interface_delete(UX_SLAVE_INTERFACE *interface) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_ENDPOINT *next_endpoint; + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(interface); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_INTERFACE_DELETE, interface, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Find the first endpoints associated with this interface. */ + next_endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Parse all the endpoints. */ + while (next_endpoint != UX_NULL) + { + + /* Save this endpoint. */ + endpoint = next_endpoint; + + /* Find the next endpoint. */ + next_endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave->ux_system_slave_dcd; + + /* The endpoint must be destroyed. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_DESTROY_ENDPOINT, endpoint); + + /* Free the endpoint. */ + endpoint -> ux_slave_endpoint_status = UX_UNUSED; + + /* Make sure the endpoint instance is now cleaned up. */ + endpoint -> ux_slave_endpoint_state = 0; + endpoint -> ux_slave_endpoint_next_endpoint = UX_NULL; + endpoint -> ux_slave_endpoint_interface = UX_NULL; + endpoint -> ux_slave_endpoint_device = UX_NULL; + } + + /* It's always from first one (to delete). */ + /* Rebuild the first link. */ + device -> ux_slave_device_first_interface = interface -> ux_slave_interface_next_interface; + + /* The interface is removed from the link, its memory must be cleaned and returned to the pool. */ + interface -> ux_slave_interface_class = UX_NULL; + interface -> ux_slave_interface_class_instance = UX_NULL; + interface -> ux_slave_interface_next_interface = UX_NULL; + interface -> ux_slave_interface_first_endpoint = UX_NULL; + interface -> ux_slave_interface_status = UX_UNUSED; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_device_stack_interface_get.c b/common/core/src/ux_device_stack_interface_get.c new file mode 100644 index 0000000..38b444b --- /dev/null +++ b/common/core/src/ux_device_stack_interface_get.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_interface_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is deprecated, ux_device_stack_alternate_setting_get */ +/* does the same thing and used by the core stack. */ +/* */ +/* This function gets the current alternate setting for an interface. */ +/* */ +/* INPUT */ +/* */ +/* interface_value Value of the interface */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_interface_get(UINT interface_value) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_INTERFACE_GET, interface_value, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the control endpoint for the device. */ + endpoint = &device -> ux_slave_device_control_endpoint; + + /* If the device was in the configured state, there may be interfaces + attached to the configuration. */ + if (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Get the pointer to the first interface. */ + interface = device -> ux_slave_device_first_interface; + + /* Parse the interfaces if any. */ + while (interface != UX_NULL) + { + + /* Check if this is the interface we have an inquiry for. */ + if (interface -> ux_slave_interface_descriptor.bInterfaceNumber == interface_value) + { + + /* Get the pointer to the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Set the value of the alternate setting in the buffer. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = + (UCHAR) interface -> ux_slave_interface_descriptor.bAlternateSetting; + + /* Setup the length appropriately. */ + transfer_request -> ux_slave_transfer_request_requested_length = 1; + + /* Set the phase of the transfer to data out. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* Send the descriptor with the appropriate length to the host. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_TRANSFER_REQUEST, transfer_request); + + /* Return the function status code. */ + return(status); + } + + /* Get the next interface. */ + interface = interface -> ux_slave_interface_next_interface; + } + } + + /* The alternate setting value was not found, so we return a stall error. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + + /* Return the status to the caller. */ + return(UX_ERROR); +} + diff --git a/common/core/src/ux_device_stack_interface_set.c b/common/core/src/ux_device_stack_interface_set.c new file mode 100644 index 0000000..82bc3fd --- /dev/null +++ b/common/core/src/ux_device_stack_interface_set.c @@ -0,0 +1,277 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_interface_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets one alternate setting of one interface and */ +/* enable all endpoints associated with this alternate setting. */ +/* configuration. */ +/* */ +/* INPUT */ +/* */ +/* device_framework Address in device framework */ +/* for selected alternate setting*/ +/* device_framework_length Length of device framework */ +/* alternate_setting_value Alternate setting */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* _ux_device_stack_interface_start Start interface */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_interface_set(UCHAR * device_framework, ULONG device_framework_length, + ULONG alternate_setting_value) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_INTERFACE *interface_link; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_ENDPOINT *endpoint_link; +ULONG descriptor_length; +UCHAR descriptor_type; +ULONG endpoints_pool_number; +ULONG interfaces_pool_number; +UINT status; + + UX_PARAMETER_NOT_USED(alternate_setting_value); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_INTERFACE_SET, alternate_setting_value, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Find a free interface in the pool and hook it to the + existing interface. */ + interface = device -> ux_slave_device_interfaces_pool; + interfaces_pool_number = device -> ux_slave_device_interfaces_pool_number; + while (interfaces_pool_number != 0) + { + /* Check if this interface is free. */ + if (interface -> ux_slave_interface_status == UX_UNUSED) + { + /* Mark this interface as used now. */ + interface -> ux_slave_interface_status = UX_USED; + break; + } + + /* Try the next interface. */ + interface++; + + /* Decrement the number of interfaces left to scan in the pool. */ + interfaces_pool_number--; + } + + /* Did we find a free interface ? */ + if (interfaces_pool_number == 0) + return(UX_MEMORY_INSUFFICIENT); + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, interface, 0, 0, 0) + + /* Parse the descriptor in something more readable. */ + _ux_utility_descriptor_parse(device_framework, + _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, + (UCHAR *) &interface -> ux_slave_interface_descriptor); + + /* Attach this interface to the end of the interface chain. */ + if (device -> ux_slave_device_first_interface == UX_NULL) + { + + device -> ux_slave_device_first_interface = interface; + } + else + { + /* Multiple interfaces exist, so find the end of the chain. */ + interface_link = device -> ux_slave_device_first_interface; + while (interface_link -> ux_slave_interface_next_interface != UX_NULL) + interface_link = interface_link -> ux_slave_interface_next_interface; + interface_link -> ux_slave_interface_next_interface = interface; + } + + /* Point beyond the interface descriptor. */ + device_framework_length -= (ULONG) *device_framework; + device_framework += (ULONG) *device_framework; + + /* Parse the device framework and locate endpoint descriptor(s). */ + while (device_framework_length != 0) + { + + /* Get the length of the current descriptor. */ + descriptor_length = (ULONG) *device_framework; + + /* And its type. */ + descriptor_type = *(device_framework + 1); + + /* Check if this is an endpoint descriptor. */ + switch(descriptor_type) + { + + case UX_ENDPOINT_DESCRIPTOR_ITEM: + + /* Find a free endpoint in the pool and hook it to the + existing interface after it's created by DCD. */ + endpoint = device -> ux_slave_device_endpoints_pool; + endpoints_pool_number = device -> ux_slave_device_endpoints_pool_number; + while (endpoints_pool_number != 0) + { + /* Check if this endpoint is free. */ + if (endpoint -> ux_slave_endpoint_status == UX_UNUSED) + { + /* Mark this endpoint as used now. */ + endpoint -> ux_slave_endpoint_status = UX_USED; + break; + } + + /* Try the next endpoint. */ + endpoint++; + + /* Decrement the number of endpoints to scan from the pool. */ + endpoints_pool_number--; + } + + /* Did we find a free endpoint ? */ + if (endpoints_pool_number == 0) + return(UX_MEMORY_INSUFFICIENT); + + /* Parse the descriptor in something more readable. */ + _ux_utility_descriptor_parse(device_framework, + _ux_system_endpoint_descriptor_structure, + UX_ENDPOINT_DESCRIPTOR_ENTRIES, + (UCHAR *) &endpoint -> ux_slave_endpoint_descriptor); + + /* Now we create a transfer request to accept transfer on this endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* We store the endpoint in the transfer request as well. */ + transfer_request -> ux_slave_transfer_request_endpoint = endpoint; + + /* By default the timeout is infinite on request. */ + transfer_request -> ux_slave_transfer_request_timeout = UX_WAIT_FOREVER; + + /* Attach the interface to the endpoint. */ + endpoint -> ux_slave_endpoint_interface = interface; + + /* Attach the device to the endpoint. */ + endpoint -> ux_slave_endpoint_device = device; + + /* Create the endpoint at the DCD level. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_CREATE_ENDPOINT, (VOID *) endpoint); + + /* Do a sanity check on endpoint creation. */ + if (status != UX_SUCCESS) + { + + /* Error was returned, endpoint cannot be created. */ + endpoint -> ux_slave_endpoint_status = UX_UNUSED; + return(status); + } + + /* Attach this endpoint to the end of the endpoint chain. */ + if (interface -> ux_slave_interface_first_endpoint == UX_NULL) + { + + interface -> ux_slave_interface_first_endpoint = endpoint; + } + else + { + /* Multiple endpoints exist, so find the end of the chain. */ + endpoint_link = interface -> ux_slave_interface_first_endpoint; + while (endpoint_link -> ux_slave_endpoint_next_endpoint != UX_NULL) + endpoint_link = endpoint_link -> ux_slave_endpoint_next_endpoint; + endpoint_link -> ux_slave_endpoint_next_endpoint = endpoint; + } + break; + + case UX_CONFIGURATION_DESCRIPTOR_ITEM: + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* If the descriptor is a configuration or interface, + we have parsed and mounted all endpoints. + The interface attached to this configuration must be started at the class level. */ + status = _ux_device_stack_interface_start(interface); + + /* Return the status to the caller. */ + return(status); + + default: + break; + } + + /* Adjust what is left of the device framework. */ + device_framework_length -= descriptor_length; + + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + + /* The interface attached to this configuration must be started at the class + level. */ + status = _ux_device_stack_interface_start(interface); + + /* Return the status to the caller. */ + return(status); +} + diff --git a/common/core/src/ux_device_stack_interface_start.c b/common/core/src/ux_device_stack_interface_start.c new file mode 100644 index 0000000..98747ef --- /dev/null +++ b/common/core/src/ux_device_stack_interface_start.c @@ -0,0 +1,130 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_interface_start PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts an interface associated with the enabled */ +/* configuration. */ +/* */ +/* INPUT */ +/* */ +/* interface Pointer to interface */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_class_entry_function) Device class entry function */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_interface_start(UX_SLAVE_INTERFACE *interface) +{ + +UX_SLAVE_DEVICE *device; +UX_SLAVE_CLASS *class; +UINT status; +UX_SLAVE_CLASS_COMMAND class_command; + + + /* Get the class for the interface. */ + class = _ux_system_slave -> ux_system_slave_interface_class_array[interface -> ux_slave_interface_descriptor.bInterfaceNumber]; + + /* Check if class driver is available. */ + if (class == UX_NULL) + + /* There is no class driver supported. */ + return (UX_NO_CLASS_MATCH); + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Build all the fields of the Class Command. */ + class_command.ux_slave_class_command_request = UX_SLAVE_CLASS_COMMAND_QUERY; + class_command.ux_slave_class_command_interface = (VOID *)interface; + class_command.ux_slave_class_command_class = interface -> ux_slave_interface_descriptor.bInterfaceClass; + class_command.ux_slave_class_command_subclass = interface -> ux_slave_interface_descriptor.bInterfaceSubClass; + class_command.ux_slave_class_command_protocol = interface -> ux_slave_interface_descriptor.bInterfaceProtocol; + class_command.ux_slave_class_command_vid = device -> ux_slave_device_descriptor.idVendor; + class_command.ux_slave_class_command_pid = device -> ux_slave_device_descriptor.idProduct; + + /* We can now memorize the interface pointer associated with this class. */ + class -> ux_slave_class_interface = interface; + + /* We have found a potential candidate. Call this registered class entry function. */ + status = class -> ux_slave_class_entry_function(&class_command); + + /* The status tells us if the registered class wants to own this class. */ + if (status == UX_SUCCESS) + { + + /* Store the class container. */ + class_command.ux_slave_class_command_class_ptr = class; + + /* Store the command. */ + class_command.ux_slave_class_command_request = UX_SLAVE_CLASS_COMMAND_ACTIVATE; + + /* Activate the class. */ + status = class -> ux_slave_class_entry_function(&class_command); + + /* If the class was successfully activated, set the class for the interface. */ + if(status == UX_SUCCESS) + interface -> ux_slave_interface_class = class; + + return(status); + } + + /* There is no driver who want to own this class! */ + return(UX_NO_CLASS_MATCH); +} + diff --git a/common/core/src/ux_device_stack_microsoft_extension_register.c b/common/core/src/ux_device_stack_microsoft_extension_register.c new file mode 100644 index 0000000..983e535 --- /dev/null +++ b/common/core/src/ux_device_stack_microsoft_extension_register.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_microsoft_extension_register PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers the Microsoft extensions to support vendor */ +/* commands before the device is configured. */ +/* */ +/* INPUT */ +/* */ +/* vendor_command Vendor Command. */ +/* application_callback Application Callback */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_microsoft_extension_register(ULONG vendor_request, + UINT (*vendor_request_function)(ULONG, ULONG, ULONG, ULONG, UCHAR *, ULONG *)) +{ + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_MICROSOFT_EXTENSION_REGISTER, 0, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Store the vendor command. */ + _ux_system_slave -> ux_system_slave_device_vendor_request = vendor_request; + _ux_system_slave -> ux_system_slave_device_vendor_request_function = vendor_request_function; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_device_stack_set_feature.c b/common/core/src/ux_device_stack_set_feature.c new file mode 100644 index 0000000..e8cca96 --- /dev/null +++ b/common/core/src/ux_device_stack_set_feature.c @@ -0,0 +1,195 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_set_feature PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets a specific feature (Device, Interface, */ +/* Endpoint ....). */ +/* */ +/* INPUT */ +/* */ +/* request_type Request type */ +/* request_value Request value */ +/* request_index Request index */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) DCD controller function */ +/* */ +/* CALLED BY */ +/* */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_set_feature(ULONG request_type, ULONG request_value, ULONG request_index) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_DEVICE *device; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_ENDPOINT *endpoint_target; + + UX_PARAMETER_NOT_USED(request_value); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_SET_FEATURE, request_value, request_index, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the control endpoint for the device. */ + endpoint = &device -> ux_slave_device_control_endpoint; + + /* The feature can be for either the device or the endpoint. */ + switch (request_type & UX_REQUEST_TARGET) + { + + case UX_REQUEST_TARGET_DEVICE: + + /* Check if we have a DEVICE_REMOTE_WAKEUP Feature. */ + if (request_value == UX_REQUEST_FEATURE_DEVICE_REMOTE_WAKEUP) + { + + /* Check if we have the capability. */ + if (_ux_system_slave -> ux_system_slave_remote_wakeup_capability) + { + + /* Enable the feature. */ + _ux_system_slave -> ux_system_slave_remote_wakeup_enabled = UX_TRUE; + + /* OK. */ + return (UX_SUCCESS); + } + else + + /* Protocol error. */ + return (UX_FUNCTION_NOT_SUPPORTED); + } + +#ifdef UX_OTG_SUPPORT + /* Check if we have a A_HNP_SUPPORT Feature. This is set when the Host is HNP capable. */ + if (request_value == UX_OTG_FEATURE_A_HNP_SUPPORT) + + /* Store the A_HNP_SUPPORT flag. */ + _ux_system_otg -> ux_system_otg_slave_set_feature_flag |= UX_OTG_FEATURE_A_HNP_SUPPORT; + else + { + + /* Check if the host asks us to perform HNP. If also we become the host. */ + if (request_value == UX_OTG_FEATURE_B_HNP_ENABLE) + { + + /* The ISR will pick up the suspend event and check if we need to become IDLE or HOST. */ + _ux_system_otg -> ux_system_otg_slave_set_feature_flag |= UX_OTG_FEATURE_B_HNP_ENABLE; + + } + + } +#endif + + break; + + case UX_REQUEST_TARGET_ENDPOINT: + + /* The only set feature for endpoint is ENDPOINT_STALL. This forces + the endpoint to the stall situation. + We need to find the endpoint through the interface(s). */ + interface = device -> ux_slave_device_first_interface; + + while (interface != UX_NULL) + { + + /* Get the first endpoint for this interface. */ + endpoint_target = interface -> ux_slave_interface_first_endpoint; + + /* Parse all the endpoints. */ + while (endpoint_target != UX_NULL) + { + + /* Check the endpoint index. */ + if (endpoint_target -> ux_slave_endpoint_descriptor.bEndpointAddress == request_index) + { + + /* Stall the endpoint. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint_target); + + /* Return the function status. */ + return(UX_SUCCESS); + } + + /* Next endpoint. */ + endpoint_target = endpoint_target -> ux_slave_endpoint_next_endpoint; + } + + /* Next interface. */ + interface = interface -> ux_slave_interface_next_interface; + } + + /* We get here when the endpoint is wrong. Should not happen though. */ + /* Intentionally fall through into the default case. */ + /* fall through */ + default: + + /* We stall the command. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + + /* No more work to do here. The command failed but the upper layer does not depend on it. */ + return(UX_SUCCESS); + } + + /* Return the function status. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_device_stack_transfer_abort.c b/common/core/src/ux_device_stack_transfer_abort.c new file mode 100644 index 0000000..49a58d9 --- /dev/null +++ b/common/core/src/ux_device_stack_transfer_abort.c @@ -0,0 +1,126 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_transfer_abort PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function aborts a pending transfer request that has been */ +/* previously submitted. This function only cancels a specific */ +/* transfer request. */ +/* */ +/* The call back to the function will have the */ +/* UX_TRANSFER_STATUS_ABORT status */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* completion_code Completion code */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_semaphore_put Put semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_transfer_abort(UX_SLAVE_TRANSFER *transfer_request, ULONG completion_code) +{ + +TX_INTERRUPT_SAVE_AREA + +UX_SLAVE_DCD *dcd; + + UX_PARAMETER_NOT_USED(completion_code); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_TRANSFER_ABORT, transfer_request, completion_code, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Sets the completion code due to bus reset. */ + transfer_request -> ux_slave_transfer_request_completion_code = UX_TRANSFER_BUS_RESET; + + /* Ensure we're not preempted by the transfer completion ISR. */ + TX_DISABLE + + /* It's possible the transfer already completed. Ensure it hasn't before doing the abort. */ + if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) + { + + /* Call the DCD if necessary for cleaning up the pending transfer. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_TRANSFER_ABORT, (VOID *) transfer_request); + + /* Restore interrupts. Note that the transfer request should not be modified now. */ + TX_RESTORE + + /* We need to set the completion code for the transfer to aborted. Note + that the transfer request function cannot simultaneously modify this + because if the transfer was pending, then the transfer's thread is + currently waiting for it to complete. */ + transfer_request -> ux_slave_transfer_request_status = UX_TRANSFER_STATUS_ABORT; + + /* Wake up the device driver who is waiting on the semaphore. */ + _ux_utility_semaphore_put(&transfer_request -> ux_slave_transfer_request_semaphore); + } + else + { + + /* Restore interrupts. */ + TX_RESTORE + } + + /* This function never fails. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_device_stack_transfer_all_request_abort.c b/common/core/src/ux_device_stack_transfer_all_request_abort.c new file mode 100644 index 0000000..48c7d3f --- /dev/null +++ b/common/core/src/ux_device_stack_transfer_all_request_abort.c @@ -0,0 +1,89 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_transfer_all_request_abort PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cancels all the transfer requests attached to an */ +/* endpoint. The endpoint is not reset and its toggle state is left */ +/* the same. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* completion_code Completion code */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_abort Transfer abort */ +/* */ +/* CALLED BY */ +/* */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_transfer_all_request_abort(UX_SLAVE_ENDPOINT *endpoint, ULONG completion_code) +{ + +UX_SLAVE_TRANSFER *transfer_request; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_TRANSFER_ALL_REQUEST_ABORT, endpoint, completion_code, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the transfer request for this endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Abort this request. */ + _ux_device_stack_transfer_abort(transfer_request, completion_code); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_device_stack_transfer_request.c b/common/core/src/ux_device_stack_transfer_request.c new file mode 100644 index 0000000..20f3aa9 --- /dev/null +++ b/common/core/src/ux_device_stack_transfer_request.c @@ -0,0 +1,183 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_transfer_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a USB transaction. On entry the */ +/* transfer request gives the endpoint pipe selected for this */ +/* transaction and the parameters associated with the transfer */ +/* (data payload, length of transaction). */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* slave_length Length returned by host */ +/* host_length Length asked by host */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) Slave DCD dispatch function */ +/* _ux_utility_delay_ms Delay ms */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_transfer_request(UX_SLAVE_TRANSFER *transfer_request, + ULONG slave_length, + ULONG host_length) +{ + +TX_INTERRUPT_SAVE_AREA + +UX_SLAVE_DCD *dcd; +UINT status; +UX_SLAVE_ENDPOINT *endpoint; +ULONG device_state; + + + /* Do we have to skip this transfer? */ + if (transfer_request -> ux_slave_transfer_request_status_phase_ignore == UX_TRUE) + return(UX_SUCCESS); + + /* Disable interrupts to prevent the disconnection ISR from preempting us + while we check the device state and set the transfer status. */ + TX_DISABLE + + /* Get the device state. */ + device_state = _ux_system_slave -> ux_system_slave_device.ux_slave_device_state; + + /* We can only transfer when the device is ATTACHED, ADDRESSED OR CONFIGURED. */ + if ((device_state == UX_DEVICE_ATTACHED) || (device_state == UX_DEVICE_ADDRESSED) + || (device_state == UX_DEVICE_CONFIGURED)) + + /* Set the transfer to pending. */ + transfer_request -> ux_slave_transfer_request_status = UX_TRANSFER_STATUS_PENDING; + + else + { + + /* The device is in an invalid state. Restore interrupts and return error. */ + TX_RESTORE + return(UX_TRANSFER_NOT_READY); + } + + /* Restore interrupts. */ + TX_RESTORE + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_TRANSFER_REQUEST, transfer_request, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the endpoint associated with this transaction. */ + endpoint = transfer_request -> ux_slave_transfer_request_endpoint; + + /* If the endpoint is non Control, check the endpoint direction and set the data phase direction. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) != UX_CONTROL_ENDPOINT) + { + + /* Check if the endpoint is STALLED. In this case, we must refuse the transaction until the endpoint + has been reset by the host. */ + while (endpoint -> ux_slave_endpoint_state == UX_ENDPOINT_HALTED) + + /* Wait for 100ms for endpoint to be reset by a CLEAR_FEATURE command. */ + _ux_utility_delay_ms(100); + + /* Isolate the direction from the endpoint address. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + else + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_IN; + } + + /* See if we need to force a zero length packet at the end of the transfer. + This happens on a DATA IN and when the host requested length is not met + and the last packet is on a boundary. If slave_length is zero, then it is + a explicit ZLP request, no need to force ZLP. */ + if ((transfer_request -> ux_slave_transfer_request_phase == UX_TRANSFER_PHASE_DATA_OUT) && + (slave_length != 0) && (host_length != slave_length) && + (slave_length % endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize) == 0) + { + + /* If so force Zero Length Packet. */ + transfer_request -> ux_slave_transfer_request_force_zlp = UX_TRUE; + } + else + { + + /* Condition is not met, do not force a Zero Length Packet. */ + transfer_request -> ux_slave_transfer_request_force_zlp = UX_FALSE; + } + + /* Reset the number of bytes sent/received. */ + transfer_request -> ux_slave_transfer_request_actual_length = 0; + + /* Determine how many bytes to send in this transaction. We keep track of the original + length and have a working length. */ + transfer_request -> ux_slave_transfer_request_requested_length = slave_length; + transfer_request -> ux_slave_transfer_request_in_transfer_length = slave_length; + + /* Save the buffer pointer. */ + transfer_request -> ux_slave_transfer_request_current_data_pointer = + transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Call the DCD driver transfer function. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_TRANSFER_REQUEST, transfer_request); + + /* And return the status. */ + return(status); + +} + diff --git a/common/core/src/ux_device_stack_uninitialize.c b/common/core/src/ux_device_stack_uninitialize.c new file mode 100644 index 0000000..7a1c63e --- /dev/null +++ b/common/core/src/ux_device_stack_uninitialize.c @@ -0,0 +1,122 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_stack_uninitialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function uninitializes the generic portion of the device side */ +/* of USBX. */ +/* */ +/* INPUT */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_free Free */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_stack_uninitialize(VOID) +{ +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoints_pool; +UX_SLAVE_TRANSFER *transfer_request; +ULONG endpoints_found; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_STACK_INITIALIZE, 0, 0, 0, 0, UX_TRACE_DEVICE_STACK_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Free class memory. */ + _ux_utility_memory_free(_ux_system_slave -> ux_system_slave_class_array); + + /* Allocate some memory for the Control Endpoint. First get the address of the transfer request for the + control endpoint. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Free memory for the control endpoint buffer. */ + _ux_utility_memory_free(transfer_request -> ux_slave_transfer_request_data_pointer); + + /* Get the number of endpoints found in the device framework. */ + endpoints_found = device -> ux_slave_device_endpoints_pool_number; + + /* Get the endpoint pool address in the device container. */ + endpoints_pool = device -> ux_slave_device_endpoints_pool; + + /* Parse all endpoints and fee memory and semaphore. */ + while (endpoints_found-- != 0) + { + /* Free the memory for endpoint data pointer. */ + _ux_utility_memory_free(endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_data_pointer); + + /* Remove the TX semaphore for the endpoint. */ + _ux_utility_semaphore_delete(&endpoints_pool -> ux_slave_endpoint_transfer_request.ux_slave_transfer_request_semaphore); + + /* Next endpoint. */ + endpoints_pool++; + } + + /* Free the endpoint pool address in the device container. */ + _ux_utility_memory_free(device -> ux_slave_device_endpoints_pool); + + /* Free memory for interface pool. */ + _ux_utility_memory_free(device -> ux_slave_device_interfaces_pool); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + + + + diff --git a/common/core/src/ux_hcd_sim_host_asynch_queue_process.c b/common/core/src/ux_hcd_sim_host_asynch_queue_process.c new file mode 100644 index 0000000..d771e9e --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_asynch_queue_process.c @@ -0,0 +1,79 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_asynch_queue_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function process the asynchronous transactions that happened */ +/* in the last frame. We read the ATL buffer and search for completed */ +/* PTDs and reflect the completion in the higher level ED/TD. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_sim_host_asynch_queue_process(UX_HCD_SIM_HOST *hcd_sim_host) +{ + + UX_PARAMETER_NOT_USED(hcd_sim_host); + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_hcd_sim_host_asynch_schedule.c b/common/core/src/ux_hcd_sim_host_asynch_schedule.c new file mode 100644 index 0000000..a0cefc4 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_asynch_schedule.c @@ -0,0 +1,126 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_asynch_schedule PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function schedules new transfers from the control/bulk lists. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_transaction_schedule Schedule simulator transaction*/ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_sim_host_asynch_schedule(UX_HCD_SIM_HOST *hcd_sim_host) +{ + +UX_HCD_SIM_HOST_ED *ed; +UX_HCD_SIM_HOST_ED *first_ed; +UINT status; + + + /* Get the pointer to the current ED in the asynchronous list. */ + ed = hcd_sim_host -> ux_hcd_sim_host_asynch_current_ed; + + /* Check if there is any ED candidate in the asynch list. */ + if (ed == UX_NULL) + { + + /* Check if there is any ED in the asynch list. If none, nothing to do. */ + if (hcd_sim_host -> ux_hcd_sim_host_asynch_head_ed == UX_NULL) + return; + else + ed = hcd_sim_host -> ux_hcd_sim_host_asynch_head_ed; + } + + /* Remember this ED. */ + first_ed = ed; + + /* In simulation, we are not tied to bandwidth limitation. */ + do + { + + /* Check if this ED has a tail and head TD different. */ + if (ed -> ux_sim_host_ed_tail_td != ed -> ux_sim_host_ed_head_td) + { + + /* Schedule this transaction with the device simulator. */ + status = _ux_hcd_sim_host_transaction_schedule(hcd_sim_host, ed); + + /* If the TD has been added to the list, we can memorize this ED has + being served and make the next ED as the one to be first scanned + at the next SOF. */ + if (status == UX_SUCCESS) + { + + if (ed -> ux_sim_host_ed_next_ed == UX_NULL) + hcd_sim_host -> ux_hcd_sim_host_asynch_current_ed = hcd_sim_host -> ux_hcd_sim_host_asynch_head_ed; + else + hcd_sim_host -> ux_hcd_sim_host_asynch_current_ed = ed -> ux_sim_host_ed_next_ed; + } + } + + /* Point to the next ED in the list. Check if at end of list. */ + if (ed -> ux_sim_host_ed_next_ed == UX_NULL) + ed = hcd_sim_host -> ux_hcd_sim_host_asynch_head_ed; + else + ed = ed -> ux_sim_host_ed_next_ed; + + } while ((ed) && (ed != first_ed)); +} + diff --git a/common/core/src/ux_hcd_sim_host_asynchronous_endpoint_create.c b/common/core/src/ux_hcd_sim_host_asynchronous_endpoint_create.c new file mode 100644 index 0000000..0cb523f --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_asynchronous_endpoint_create.c @@ -0,0 +1,122 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_asynchronous_endpoint_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will create an asynchronous endpoint. The control */ +/* and bulk endpoints fall into this category. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_ed_obtain Obtain host ED */ +/* _ux_hcd_sim_host_regular_td_obtain Obtain host regular TD */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_asynchronous_endpoint_create(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint) +{ + +UX_HCD_SIM_HOST_ED *ed; +UX_HCD_SIM_HOST_ED *head_ed; +UX_HCD_SIM_HOST_TD *td; + + + /* We need to take into account the nature of the HCD to define the max size + of any transfer in the transfer request. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_maximum_length = UX_HCD_SIM_HOST_MAX_PAYLOAD; + + /* Obtain a ED for this new endpoint. This ED will live as long as the endpoint is active + and will be the container for the TDs. */ + ed = _ux_hcd_sim_host_ed_obtain(hcd_sim_host); + if (ed == UX_NULL) + return(UX_NO_ED_AVAILABLE); + + /* Obtain a dummy TD for terminating the ED transfer chain. */ + td = _ux_hcd_sim_host_regular_td_obtain(hcd_sim_host); + if (td == UX_NULL) + { + + ed -> ux_sim_host_ed_status = UX_UNUSED; + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the ED to the endpoint container. */ + endpoint -> ux_endpoint_ed = (VOID *) ed; + + /* Now do the opposite, attach the ED container to the physical ED. */ + ed -> ux_sim_host_ed_endpoint = endpoint; + + /* Hook the TD to both the tail and head of the ED. */ + ed -> ux_sim_host_ed_tail_td = td; + ed -> ux_sim_host_ed_head_td = td; + + /* Attach this ED to the asynch list. */ + head_ed = hcd_sim_host -> ux_hcd_sim_host_asynch_head_ed; + ed -> ux_sim_host_ed_next_ed = head_ed; + hcd_sim_host -> ux_hcd_sim_host_asynch_head_ed = ed; + + /* Build the back chaining pointer. The previous head ED needs to know about the + inserted ED. */ + if (head_ed != UX_NULL) + head_ed -> ux_sim_host_ed_previous_ed = ed; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_asynchronous_endpoint_destroy.c b/common/core/src/ux_hcd_sim_host_asynchronous_endpoint_destroy.c new file mode 100644 index 0000000..71bbda2 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_asynchronous_endpoint_destroy.c @@ -0,0 +1,121 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_asynchronous_endpoint_destroy PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will destroy an asynchronous endpoint. The control */ +/* and bulk endpoints fall into this category. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_asynchronous_endpoint_destroy(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint) +{ + +UX_HCD_SIM_HOST_ED *ed; +UX_HCD_SIM_HOST_ED *previous_ed; +UX_HCD_SIM_HOST_ED *next_ed; +UX_HCD_SIM_HOST_TD *td; + + + /* From the endpoint container fetch the host simulator ED descriptor. */ + ed = (UX_HCD_SIM_HOST_ED *) endpoint -> ux_endpoint_ed; + + /* Get the previous ED in the list for this ED. */ + previous_ed = ed -> ux_sim_host_ed_previous_ed; + + /* Get the next ED in the list for this ED. */ + next_ed = ed -> ux_sim_host_ed_next_ed; + + /* If the previous ED is NULL, we are at trying to remove the head ED. */ + if (previous_ed == UX_NULL) + + /* Store the new endpoint in the control list. */ + hcd_sim_host -> ux_hcd_sim_host_asynch_head_ed = next_ed; + else + + /* The previous ED points now to the ED after the ED we are removing. */ + previous_ed -> ux_sim_host_ed_next_ed = next_ed; + + /* Update the previous ED pointer in the next ED if exists. */ + if (next_ed != UX_NULL) + next_ed -> ux_sim_host_ed_previous_ed = previous_ed; + + /* Determine if we need to adjust the current ED. */ + if (hcd_sim_host -> ux_hcd_sim_host_asynch_current_ed == ed) + { + + /* Move the current to the next. */ + hcd_sim_host -> ux_hcd_sim_host_asynch_current_ed = next_ed; + } + + /* We need to free the dummy TD that was attached to the ED. */ + td = ed -> ux_sim_host_ed_tail_td; + td -> ux_sim_host_td_status = UX_UNUSED; + + /* Now we can safely make the ED free. */ + ed -> ux_sim_host_ed_status = UX_UNUSED; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_ed_obtain.c b/common/core/src/ux_hcd_sim_host_ed_obtain.c new file mode 100644 index 0000000..1045bd5 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_ed_obtain.c @@ -0,0 +1,102 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_ed_obtain PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains a free ED from the ED list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* */ +/* OUTPUT */ +/* */ +/* UX_HCD_SIM_HOST_ED * Pointer to ED */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_set Set memory block */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_HCD_SIM_HOST_ED *_ux_hcd_sim_host_ed_obtain(UX_HCD_SIM_HOST *hcd_sim_host) +{ + +UX_HCD_SIM_HOST_ED *ed; +ULONG ed_index; + + + /* Start the search from the beginning of the list. */ + ed = hcd_sim_host -> ux_hcd_sim_host_ed_list; + for(ed_index = 0; ed_index < _ux_system_host -> ux_system_host_max_ed; ed_index++) + { + + /* Check the ED status, a free ED is marked with the UNUSED flag. */ + if (ed -> ux_sim_host_ed_status == UX_UNUSED) + { + + /* The ED may have been used, so we reset all fields. */ + _ux_utility_memory_set(ed, 0, sizeof(UX_HCD_SIM_HOST_ED)); + + /* This ED is now marked as USED. */ + ed -> ux_sim_host_ed_status = UX_USED; + + /* Return ED pointer. */ + return(ed); + } + + /* Point to the next ED. */ + ed++; + } + + /* There is no available ED in the ED list. */ + return(UX_NULL); +} + diff --git a/common/core/src/ux_hcd_sim_host_ed_td_clean.c b/common/core/src/ux_hcd_sim_host_ed_td_clean.c new file mode 100644 index 0000000..658c616 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_ed_td_clean.c @@ -0,0 +1,96 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_ed_td_clean PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function process cleans the ED of all TDs except the last */ +/* dummy TD. */ +/* */ +/* INPUT */ +/* */ +/* ed Pointer to ED */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_sim_host_ed_td_clean(UX_HCD_SIM_HOST_ED *ed) +{ + +UX_HCD_SIM_HOST_TD *head_td; +UX_HCD_SIM_HOST_TD *tail_td; + + + /* Remove all the tds from this ED and leave the head and tail pointing + to the dummy TD. */ + head_td = ed -> ux_sim_host_ed_head_td; + tail_td = ed -> ux_sim_host_ed_tail_td; + + /* Free all tds attached to the ED. */ + while (head_td != tail_td) + { + + /* Mark the current head TD as free. */ + head_td -> ux_sim_host_td_status = UX_UNUSED; + + /* Update the head TD with the next TD. */ + ed -> ux_sim_host_ed_head_td = head_td -> ux_sim_host_td_next_td; + + /* Now the new head_td is the next TD in the chain. */ + head_td = ed -> ux_sim_host_ed_head_td; + } +} + diff --git a/common/core/src/ux_hcd_sim_host_endpoint_reset.c b/common/core/src/ux_hcd_sim_host_endpoint_reset.c new file mode 100644 index 0000000..49eed9e --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_endpoint_reset.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_endpoint_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will reset an endpoint. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_endpoint_reset(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint) +{ + +UX_HCD_SIM_HOST_ED *ed; + + UX_PARAMETER_NOT_USED(hcd_sim_host); + + /* From the endpoint container fetch the host simulator ED descriptor. */ + ed = (UX_HCD_SIM_HOST_ED *) endpoint -> ux_endpoint_ed; + + /* Reset the data0/data1 toggle bit in the Head TD. */ + ed -> ux_sim_host_ed_toggle = 0; + + /* This operation never fails. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_entry.c b/common/core/src/ux_hcd_sim_host_entry.c new file mode 100644 index 0000000..02cce35 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_entry.c @@ -0,0 +1,273 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function dispatch the HCD function internally to the simulator */ +/* controller driver. */ +/* */ +/* INPUT */ +/* */ +/* hcd Pointer to HCD */ +/* function Function for driver to perform*/ +/* parameter Pointer to parameter(s) */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_asynch_queue_process Process asynch queue */ +/* _ux_hcd_sim_host_asynch_schedule Schedule async work */ +/* _ux_hcd_sim_host_asynchronous_endpoint_create Create async endpoint */ +/* _ux_hcd_sim_host_asynchronous_endpoint_destroy Destroy async endpoint */ +/* _ux_hcd_sim_host_endpoint_reset Reset endpoint */ +/* _ux_hcd_sim_host_frame_number_get Get frame number */ +/* _ux_hcd_sim_host_interrupt_endpoint_create Create endpoint */ +/* _ux_hcd_sim_host_iso_queue_process Process iso queue */ +/* _ux_hcd_sim_host_iso_schedule Schedule iso work */ +/* _ux_hcd_sim_host_isochronous_endpoint_create Create iso endpoint */ +/* _ux_hcd_sim_host_periodic_endpoint_destroy Destroy endpoint */ +/* _ux_hcd_sim_host_periodic_schedule Schedule periodic */ +/* _ux_hcd_sim_host_port_status_get Get port status */ +/* _ux_hcd_sim_host_port_reset Reset port */ +/* _ux_hcd_sim_host_request_transfer Request transfer */ +/* _ux_hcd_sim_host_transfer_abort Abort transfer */ +/* */ +/* CALLED BY */ +/* */ +/* Host Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_entry(UX_HCD *hcd, UINT function, VOID *parameter) +{ + +UINT status = 0; +UX_HCD_SIM_HOST *hcd_sim_host; + + + /* Check the status of the controller. */ + if (hcd -> ux_hcd_status == UX_UNUSED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_CONTROLLER_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONTROLLER_UNKNOWN, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONTROLLER_UNKNOWN); + } + + /* Get the pointer to the host simulator HCD. */ + hcd_sim_host = (UX_HCD_SIM_HOST *) hcd -> ux_hcd_controller_hardware; + + /* look at the function and route it. */ + switch(function) + { + + case UX_HCD_DISABLE_CONTROLLER: + + status = UX_SUCCESS; + break; + + + case UX_HCD_GET_PORT_STATUS: + + status = _ux_hcd_sim_host_port_status_get(hcd_sim_host, (ULONG) (ALIGN_TYPE) parameter); + break; + + + case UX_HCD_ENABLE_PORT: + + status = UX_SUCCESS; + break; + + + case UX_HCD_DISABLE_PORT: + + status = UX_SUCCESS; + break; + + + case UX_HCD_POWER_ON_PORT: + + status = UX_SUCCESS; + break; + + + case UX_HCD_POWER_DOWN_PORT: + + status = UX_SUCCESS; + break; + + + case UX_HCD_SUSPEND_PORT: + + status = UX_SUCCESS; + break; + + + case UX_HCD_RESUME_PORT: + + status = UX_SUCCESS; + break; + + + case UX_HCD_RESET_PORT: + + status = _ux_hcd_sim_host_port_reset(hcd_sim_host, (ULONG) (ALIGN_TYPE) parameter); + break; + + + case UX_HCD_GET_FRAME_NUMBER: + + status = _ux_hcd_sim_host_frame_number_get(hcd_sim_host, (ULONG *) parameter); + break; + + + case UX_HCD_SET_FRAME_NUMBER: + + status = UX_SUCCESS; + break; + + + case UX_HCD_TRANSFER_REQUEST: + + status = _ux_hcd_sim_host_request_transfer(hcd_sim_host, (UX_TRANSFER *) parameter); + break; + + + case UX_HCD_TRANSFER_ABORT: + + status = _ux_hcd_sim_host_transfer_abort(hcd_sim_host, (UX_TRANSFER *) parameter); + break; + + + case UX_HCD_CREATE_ENDPOINT: + + switch ((((UX_ENDPOINT*) parameter) -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + case UX_BULK_ENDPOINT: + + status = _ux_hcd_sim_host_asynchronous_endpoint_create(hcd_sim_host, (UX_ENDPOINT*) parameter); + break; + + + case UX_INTERRUPT_ENDPOINT: + + status = _ux_hcd_sim_host_interrupt_endpoint_create(hcd_sim_host, (UX_ENDPOINT*) parameter); + break; + + + case UX_ISOCHRONOUS_ENDPOINT: + + status = _ux_hcd_sim_host_isochronous_endpoint_create(hcd_sim_host, (UX_ENDPOINT*) parameter); + break; + + } + break; + + + case UX_HCD_DESTROY_ENDPOINT: + + switch ((((UX_ENDPOINT*) parameter) -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + case UX_BULK_ENDPOINT: + + status = _ux_hcd_sim_host_asynchronous_endpoint_destroy(hcd_sim_host, (UX_ENDPOINT*) parameter); + break; + + + case UX_INTERRUPT_ENDPOINT: + case UX_ISOCHRONOUS_ENDPOINT: + + status = _ux_hcd_sim_host_periodic_endpoint_destroy(hcd_sim_host, (UX_ENDPOINT*) parameter); + break; + + } + break; + + + case UX_HCD_RESET_ENDPOINT: + + status = _ux_hcd_sim_host_endpoint_reset(hcd_sim_host, (UX_ENDPOINT*) parameter); + break; + + + case UX_HCD_PROCESS_DONE_QUEUE: + + _ux_hcd_sim_host_iso_queue_process(hcd_sim_host); + _ux_hcd_sim_host_asynch_queue_process(hcd_sim_host); + _ux_hcd_sim_host_iso_schedule(hcd_sim_host); + _ux_hcd_sim_host_periodic_schedule(hcd_sim_host); + _ux_hcd_sim_host_asynch_schedule(hcd_sim_host); + status = UX_SUCCESS; + break; + + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Unknown request, return an error. */ + status = UX_FUNCTION_NOT_SUPPORTED; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_hcd_sim_host_frame_number_get.c b/common/core/src/ux_hcd_sim_host_frame_number_get.c new file mode 100644 index 0000000..2b90a2d --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_frame_number_get.c @@ -0,0 +1,78 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_frame_number_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will return the frame number currently used by the */ +/* controller. This function is mostly used for isochronous purposes. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* frame_number Frame number to set */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_frame_number_get(UX_HCD_SIM_HOST *hcd_sim_host, ULONG *frame_number) +{ + + /* Pickup the frame number. */ + *frame_number = hcd_sim_host -> ux_hcd_sim_host_interrupt_count; + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_frame_number_set.c b/common/core/src/ux_hcd_sim_host_frame_number_set.c new file mode 100644 index 0000000..e593b74 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_frame_number_set.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_frame_number_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will set the current frame number to the one */ +/* specified. This function is mostly used for isochronous purposes. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* frame_number Frame number to set */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_sim_host_frame_number_set(UX_HCD_SIM_HOST *hcd_sim_host, ULONG frame_number) +{ + + UX_PARAMETER_NOT_USED(hcd_sim_host); + UX_PARAMETER_NOT_USED(frame_number); + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_hcd_sim_host_initialize.c b/common/core/src/ux_hcd_sim_host_initialize.c new file mode 100644 index 0000000..5d83260 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_initialize.c @@ -0,0 +1,191 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the simulated host controller */ +/* */ +/* INPUT */ +/* */ +/* HCD Pointer to HCD */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_periodic_tree_create Create periodic tree */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_semaphore_put Semaphore put */ +/* _ux_utility_timer_create Create timer */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_initialize(UX_HCD *hcd) +{ + +UX_HCD_SIM_HOST *hcd_sim_host; +UINT status; + + + /* The controller initialized here is of host simulator type. */ + hcd -> ux_hcd_controller_type = UX_HCD_SIM_HOST_CONTROLLER; + + /* Allocate memory for this host simulator HCD instance. */ + hcd_sim_host = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HCD_SIM_HOST)); + if (hcd_sim_host == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Set the pointer to the host simulator HCD. */ + hcd -> ux_hcd_controller_hardware = (VOID *) hcd_sim_host; + + /* Set the generic HCD owner for the host simulator HCD. */ + hcd_sim_host -> ux_hcd_sim_host_hcd_owner = hcd; + + /* Initialize the function collector for this HCD. */ + hcd -> ux_hcd_entry_function = _ux_hcd_sim_host_entry; + + /* Initialize the max bandwidth for periodic endpoints. In simulation this is + not very important. */ + hcd -> ux_hcd_available_bandwidth = UX_HCD_SIM_HOST_AVAILABLE_BANDWIDTH; + + /* Set the state of the controller to HALTED first. */ + hcd -> ux_hcd_status = UX_HCD_STATUS_HALTED; + + /* Allocate the list of EDs. All EDs are allocated on 16 byte memory boundary. */ + hcd_sim_host -> ux_hcd_sim_host_ed_list = _ux_utility_memory_allocate(UX_ALIGN_16, UX_REGULAR_MEMORY, (ULONG)sizeof(UX_HCD_SIM_HOST_ED) * _ux_system_host -> ux_system_host_max_ed); + if (hcd_sim_host -> ux_hcd_sim_host_ed_list == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + else + status = UX_SUCCESS; + + /* Allocate the list of TDs. All TDs are allocated on 32 byte memory boundary. */ + if (status == UX_SUCCESS) + { + hcd_sim_host -> ux_hcd_sim_host_td_list = _ux_utility_memory_allocate(UX_ALIGN_32, UX_REGULAR_MEMORY, (ULONG)sizeof(UX_HCD_SIM_HOST_TD) * _ux_system_host -> ux_system_host_max_td); + if (hcd_sim_host -> ux_hcd_sim_host_td_list == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Allocate the list of isochronous TDs. All TDs are allocated on 32 byte memory boundary. */ + if (status == UX_SUCCESS) + { + hcd_sim_host -> ux_hcd_sim_host_iso_td_list = _ux_utility_memory_allocate(UX_ALIGN_32, UX_REGULAR_MEMORY, (ULONG)sizeof(UX_HCD_SIM_HOST_ISO_TD) * _ux_system_host -> ux_system_host_max_iso_td); + if (hcd_sim_host -> ux_hcd_sim_host_iso_td_list == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Initialize the periodic tree. */ + if (status == UX_SUCCESS) + status = _ux_hcd_sim_host_periodic_tree_create(hcd_sim_host); + + /* Initialize the scheduler. */ + if (status == UX_SUCCESS) + { + /* Set the host controller into the operational state. */ + hcd -> ux_hcd_status = UX_HCD_STATUS_OPERATIONAL; + + /* The asynchronous queues are empty for now. */ + hcd_sim_host -> ux_hcd_sim_host_queue_empty = UX_TRUE; + + /* The periodic scheduler is not active. */ + hcd_sim_host -> ux_hcd_sim_host_periodic_scheduler_active = 0; + + /* We start a timer that will invoke the simulator every timer tick. */ + status = _ux_utility_timer_create(&hcd_sim_host -> ux_hcd_sim_host_timer, "USBX Simulation Timer", + _ux_hcd_sim_host_timer_function, (ULONG) (ALIGN_TYPE) hcd_sim_host, 1, 1, TX_AUTO_ACTIVATE); + } + + UX_TIMER_EXTENSION_PTR_SET(&(hcd_sim_host -> ux_hcd_sim_host_timer), hcd_sim_host) + + /* Free up resources and return when there is error. */ + if (status != UX_SUCCESS) + { + + /* Set the host controller into the halt state. */ + hcd -> ux_hcd_status = UX_HCD_STATUS_HALTED; + + /* The last resource, timer is not created or created error, + * no need to delete. */ + + if (hcd_sim_host -> ux_hcd_sim_host_iso_td_list) + _ux_utility_memory_free(hcd_sim_host -> ux_hcd_sim_host_iso_td_list); + if (hcd_sim_host -> ux_hcd_sim_host_td_list) + _ux_utility_memory_free(hcd_sim_host -> ux_hcd_sim_host_td_list); + if (hcd_sim_host -> ux_hcd_sim_host_ed_list) + _ux_utility_memory_free(hcd_sim_host -> ux_hcd_sim_host_ed_list); + _ux_utility_memory_free(hcd_sim_host); + + return(status); + } + + /* Get the number of ports on the controller. The number of ports needs to be reflected both + for the generic HCD container and the local sim_host container. In the simulator, + the number of ports is hardwired to 1 only. */ + hcd -> ux_hcd_nb_root_hubs = 1; + hcd_sim_host -> ux_hcd_sim_host_nb_root_hubs = 1; + + /* Something happened on this port. Signal it to the root hub thread. */ + hcd -> ux_hcd_root_hub_signal[0] = 1; + + /* We need to simulate a Root HUB Status Change for the USB stack since the simulator + has not root HUB per se. */ + status = _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); + if (status != UX_SUCCESS) + + /* Resources are still ready but + * failed to simulate Root HUB change! */ + return(UX_SEMAPHORE_ERROR); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_interrupt_endpoint_create.c b/common/core/src/ux_hcd_sim_host_interrupt_endpoint_create.c new file mode 100644 index 0000000..a42fa8d --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_interrupt_endpoint_create.c @@ -0,0 +1,180 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_interrupt_endpoint_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will create an interrupt endpoint. The interrupt */ +/* endpoint has an interval of operation from 1 to 255. The host */ +/* has no hardware scheduler but we still build an interrupt tree */ +/* similar to the host simulator controller. */ +/* */ +/* This routine will match the best interval for the host */ +/* simulator. It will also determine the best node to hook the */ +/* endpoint based on the load that already exists on the horizontal */ +/* ED chain. */ +/* */ +/* For the ones curious about this coding. The tricky part is to */ +/* understand how the interrupt matrix is constructed. We have used */ +/* EDs with the skip bit on to build a frame of anchor EDs. Each ED */ +/* creates a node for an appropriate combination of interval frequency */ +/* in the list. */ +/* */ +/* After obtaining a pointer to the list with the lowest traffic, we */ +/* traverse the list from the highest interval until we reach the */ +/* interval required. At that node, we anchor our real ED to the node */ +/* and link the ED that was attached to the node to our ED. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_ed_obtain Obtain ED */ +/* _ux_hcd_sim_host_regular_td_obtain Obtain regular TD */ +/* _ux_hcd_sim_host_least_traffic_list_get Get least traffic list */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_interrupt_endpoint_create(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint) +{ + +UX_HCD_SIM_HOST_ED *ed; +UX_HCD_SIM_HOST_ED *ed_list; +UX_HCD_SIM_HOST_ED *next_ed; +UX_HCD_SIM_HOST_TD *td; +UINT interval; +UINT interval_index; +UINT interval_sim_host; + + + /* Obtain a ED for this new endpoint. This ED will live as long as + the endpoint is active and will be the container for the TDs. */ + ed = _ux_hcd_sim_host_ed_obtain(hcd_sim_host); + if (ed == UX_NULL) + return(UX_NO_ED_AVAILABLE); + + /* Obtain a dummy TD for terminating the ED transfer chain. */ + td = _ux_hcd_sim_host_regular_td_obtain(hcd_sim_host); + if (td == UX_NULL) + { + + ed -> ux_sim_host_ed_status = UX_UNUSED; + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the ED to the endpoint container. */ + endpoint -> ux_endpoint_ed = (VOID *)ed; + + /* Now do the opposite, attach the ED container to the physical ED. */ + ed -> ux_sim_host_ed_endpoint = endpoint; + + /* Hook the TD to both the tail and head of the ED. */ + ed -> ux_sim_host_ed_tail_td = td; + ed -> ux_sim_host_ed_head_td = td; + + /* Get the list index with the least traffic. */ + ed_list = _ux_hcd_sim_host_least_traffic_list_get(hcd_sim_host); + + /* Get the interval for the endpoint and match it to a host simulator list. We match anything + that is > 32ms to the 32ms interval list, the 32ms list is list 0, 16ms list is 1... + the 1ms list is number 5. */ + interval = endpoint -> ux_endpoint_descriptor.bInterval; + interval_index = 1; + interval_sim_host = 5; + if (interval >= 32) + { + + interval_sim_host = 0; + } + else + { + + while (interval_index < 32) + { + + if (interval&interval_index) + interval_sim_host--; + interval_index = interval_index << 1; + } + } + + /* Now we need to scan the list of eds from the lowest load entry until we reach + the appropriate interval node. The depth index is the interval_sim_host value + and the 1st entry is pointed by the ED list entry. */ + while (interval_sim_host--) + { + + ed_list = ed_list -> ux_sim_host_ed_next_ed; + while (!(ed_list -> ux_sim_host_ed_status & UX_HCD_SIM_HOST_ED_STATIC)) + ed_list = ed_list -> ux_sim_host_ed_next_ed; + } + + /* We found the node entry of the ED pointer that will be the anchor for this interrupt + endpoint. Now we attach this endpoint to the anchor and rebuild the chain . */ + next_ed = ed_list -> ux_sim_host_ed_next_ed; + /* Note that if there is a crash here, it is most likely due to an invalid bInterval. */ + next_ed -> ux_sim_host_ed_previous_ed = ed; + ed -> ux_sim_host_ed_next_ed = next_ed; + ed -> ux_sim_host_ed_previous_ed = ed_list; + ed_list -> ux_sim_host_ed_next_ed = ed; + + /* There is activity in the periodic tree, the scheduler has to be active all the time. */ + hcd_sim_host -> ux_hcd_sim_host_periodic_scheduler_active++; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_iso_queue_process.c b/common/core/src/ux_hcd_sim_host_iso_queue_process.c new file mode 100644 index 0000000..7b88faa --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_iso_queue_process.c @@ -0,0 +1,78 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_iso_queue_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function process the isochronous transactions that happened */ +/* in the last frame. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_sim_host_iso_queue_process(UX_HCD_SIM_HOST *hcd_sim_host) +{ + + UX_PARAMETER_NOT_USED(hcd_sim_host); + + /* Not implemented - just return. */ + return; +} + diff --git a/common/core/src/ux_hcd_sim_host_iso_schedule.c b/common/core/src/ux_hcd_sim_host_iso_schedule.c new file mode 100644 index 0000000..f4206b5 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_iso_schedule.c @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_iso_schedule PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function schedules new transfers from isochronous list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_sim_host_iso_schedule(UX_HCD_SIM_HOST *hcd_sim_host) +{ + + UX_PARAMETER_NOT_USED(hcd_sim_host); + + /* Not currently implemented - just return. */ + return; +} + diff --git a/common/core/src/ux_hcd_sim_host_isochronous_endpoint_create.c b/common/core/src/ux_hcd_sim_host_isochronous_endpoint_create.c new file mode 100644 index 0000000..ef7f738 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_isochronous_endpoint_create.c @@ -0,0 +1,114 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_isochronous_endpoint_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates an isochronous endpoint. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_ed_obtain Obtain host ED */ +/* _ux_hcd_sim_host_isochronous_td_obtain Obtain host ISO TD */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_isochronous_endpoint_create(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint) +{ + +UX_HCD_SIM_HOST_ED *ed; +UX_HCD_SIM_HOST_ED *head_ed; +UX_HCD_SIM_HOST_ISO_TD *td; + + + /* Obtain a ED for this new endpoint. This ED will live as long as the endpoint is + active and will be the container for the TDs. */ + ed = _ux_hcd_sim_host_ed_obtain(hcd_sim_host); + if (ed == UX_NULL) + return(UX_NO_ED_AVAILABLE); + + /* Obtain a dummy isoch TD for terminating the ED transfer chain. */ + td = _ux_hcd_sim_host_isochronous_td_obtain(hcd_sim_host); + if (td == UX_NULL) + { + + ed -> ux_sim_host_ed_status = UX_UNUSED; + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the ED to the endpoint container. */ + endpoint -> ux_endpoint_ed = (VOID *) ed; + + /* Hook the TD to both the tail and head of the ED. */ + ed -> ux_sim_host_ed_tail_td = (UX_HCD_SIM_HOST_TD *) ((void *) td); + ed -> ux_sim_host_ed_head_td = (UX_HCD_SIM_HOST_TD *) ((void *) td); + + /* Attach this ED to the ISO list. */ + head_ed = hcd_sim_host -> ux_hcd_sim_host_iso_head_ed; + ed -> ux_sim_host_ed_next_ed = head_ed; + hcd_sim_host -> ux_hcd_sim_host_iso_head_ed = ed; + + /* Build the back chaining pointer. The previous head ED needs to know about the + inserted ED. */ + if (head_ed != UX_NULL) + head_ed -> ux_sim_host_ed_previous_ed = ed; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_isochronous_td_obtain.c b/common/core/src/ux_hcd_sim_host_isochronous_td_obtain.c new file mode 100644 index 0000000..fbd44b0 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_isochronous_td_obtain.c @@ -0,0 +1,102 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_isochronous_td_obtain PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains a free TD from the isochronous TD list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* */ +/* OUTPUT */ +/* */ +/* UX_HCD_SIM_HOST_ISO_TD * Pointer to host ISO ED */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_set Set memory block */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_HCD_SIM_HOST_ISO_TD *_ux_hcd_sim_host_isochronous_td_obtain(UX_HCD_SIM_HOST *hcd_sim_host) +{ + +UX_HCD_SIM_HOST_ISO_TD *td; +ULONG td_index; + + + /* Start the search from the beginning of the list. */ + td = hcd_sim_host -> ux_hcd_sim_host_iso_td_list; + for (td_index = 0; td_index < _ux_system_host -> ux_system_host_max_iso_td; td_index++) + { + + /* Check the TD status, a free TD is marked with the UX_USED flag. */ + if (td -> ux_sim_host_iso_td_status == UX_UNUSED) + { + + /* The TD may have been used, so we reset all fields. */ + _ux_utility_memory_set(td, 0, sizeof(UX_HCD_SIM_HOST_ISO_TD)); + + /* This TD is now marked as USED. */ + td -> ux_sim_host_iso_td_status = UX_USED; + + /* Success, return pointer to TD. */ + return(td); + } + + /* Move to next TD. */ + td++; + } + + /* There is no available TD in the TD list, return a NULL. */ + return(UX_NULL); +} + diff --git a/common/core/src/ux_hcd_sim_host_least_traffic_list_get.c b/common/core/src/ux_hcd_sim_host_least_traffic_list_get.c new file mode 100644 index 0000000..24982b4 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_least_traffic_list_get.c @@ -0,0 +1,136 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_least_traffic_list_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function return a pointer to the first ED in the periodic */ +/* tree that has the least traffic registered. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* */ +/* OUTPUT */ +/* */ +/* UX_HCD_SIM_HOST_ED * Pointer to host ED */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_HCD_SIM_HOST_ED *_ux_hcd_sim_host_least_traffic_list_get(UX_HCD_SIM_HOST *hcd_sim_host) +{ + +UX_HCD_SIM_HOST_ED *min_bandwidth_ed; +UX_HCD_SIM_HOST_ED *begin_ed; +UX_HCD_SIM_HOST_ED *ed; +UX_ENDPOINT *endpoint; +UINT list_index; +ULONG min_bandwidth_used; +ULONG bandwidth_used; + + + /* Reset the min bandwidth used. */ + min_bandwidth_used = 0; + + /* The first ED is the list candidate for now. */ + min_bandwidth_ed = hcd_sim_host -> ux_hcd_sim_host_interrupt_ed_list[0]; + + /* All list will be scanned. */ + for (list_index = 0; list_index < 32; list_index++) + { + + /* Reset the bandwidth for this list. */ + bandwidth_used = 0; + + /* Get the ED of the beginning of the list we parse now. */ + ed = hcd_sim_host -> ux_hcd_sim_host_interrupt_ed_list[list_index]; + + /* We keep track of the first ED for the current list. */ + begin_ed = ed; + + /* Parse the EDs in the list. */ + while (ed -> ux_sim_host_ed_next_ed != UX_NULL) + { + + /* Get the endpoint pointer from the physical ED. */ + endpoint = ed -> ux_sim_host_ed_endpoint; + + if (endpoint != UX_NULL) + { + + /* Add to the bandwidth used the max packet size pointed by this ED. */ + bandwidth_used += (ULONG) endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + } + + /* Move to next ED. */ + ed = ed -> ux_sim_host_ed_next_ed; + } + + /* We have processed a list, check the bandwidth used by this list. + If this bandwidth is the minimum, we memorize the ED. */ + if (bandwidth_used < min_bandwidth_used) + { + + /* We have found a better list with a lower used bandwidth, memorize the bandwidth + for this list. */ + min_bandwidth_used = bandwidth_used; + + /* Memorize the begin ED for this list. */ + min_bandwidth_ed = begin_ed; + } + } + + /* Return the ED list with the lowest bandwidth. */ + return(min_bandwidth_ed); +} + diff --git a/common/core/src/ux_hcd_sim_host_periodic_endpoint_destroy.c b/common/core/src/ux_hcd_sim_host_periodic_endpoint_destroy.c new file mode 100644 index 0000000..2ae407c --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_periodic_endpoint_destroy.c @@ -0,0 +1,110 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_periodic_endpoint_destroy PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will destroy an interrupt or isochronous endpoint. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_periodic_endpoint_destroy(UX_HCD_SIM_HOST *hcd_sim_host, UX_ENDPOINT *endpoint) +{ + +UX_HCD_SIM_HOST_ED *ed; +UX_HCD_SIM_HOST_ED *previous_ed; +UX_HCD_SIM_HOST_ED *next_ed; +UX_HCD_SIM_HOST_TD *td; + + + /* From the endpoint container fetch the host simulator ED descriptor. */ + ed = (UX_HCD_SIM_HOST_ED *) endpoint -> ux_endpoint_ed; + + /* Get the previous ED in the list for this ED. */ + previous_ed = ed -> ux_sim_host_ed_previous_ed; + + /* Get the next ED in the list for this ED. */ + next_ed = ed -> ux_sim_host_ed_next_ed; + + /* The previous ED points now to the ED after the ED we are removing. */ + if (previous_ed) + previous_ed -> ux_sim_host_ed_next_ed = next_ed; + + /* Update the previous ED pointer in the next ED. */ + if (next_ed) + next_ed -> ux_sim_host_ed_previous_ed = previous_ed; + + /* We need to free the dummy TD that was attached to the ED. */ + td = ed -> ux_sim_host_ed_tail_td; + td -> ux_sim_host_td_status = UX_UNUSED; + + /* Now we can safely make the ED free. */ + ed -> ux_sim_host_ed_status = UX_UNUSED; + + /* Decrement the number of interrupt endpoints active. When the counter + reaches 0, the periodic scheduler will be turned off. */ + hcd_sim_host -> ux_hcd_sim_host_periodic_scheduler_active--; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_periodic_schedule.c b/common/core/src/ux_hcd_sim_host_periodic_schedule.c new file mode 100644 index 0000000..1a6c3e2 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_periodic_schedule.c @@ -0,0 +1,109 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_periodic_schedule PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function schedules new transfers from the periodic interrupt */ +/* list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_frame_number_get Get frame number */ +/* _ux_hcd_sim_host_transaction_schedule Schedule the transaction */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_sim_host_periodic_schedule(UX_HCD_SIM_HOST *hcd_sim_host) +{ + +UX_HCD_SIM_HOST_ED *ed; +ULONG frame_number; + + /* Get the current frame number. */ + _ux_hcd_sim_host_frame_number_get(hcd_sim_host, &frame_number); + + /* Isolate the low bits to match an entry in the upper periodic entry list. */ + frame_number &= UX_HCD_SIM_HOST_PERIODIC_ENTRY_MASK; + + /* Get the first ED in the periodic list. */ + ed = hcd_sim_host -> ux_hcd_sim_host_interrupt_ed_list[frame_number]; + + /* Search for an entry in the periodic tree. */ + while (ed != UX_NULL) + { + + /* The ED has to be a real ED (not static) and has to have a different tail and head TD. */ + if ((ed -> ux_sim_host_ed_status != UX_HCD_SIM_HOST_ED_STATIC) && (ed -> ux_sim_host_ed_tail_td != ed -> ux_sim_host_ed_head_td)) + { + + /* Ensure this ED does not have the SKIP bit set and no TD are in progress. */ + if ((ed -> ux_sim_host_ed_head_td -> ux_sim_host_td_status & UX_HCD_SIM_HOST_TD_ACK_PENDING) == 0) + + /* Insert this transfer in the list of scheduled TDs if possible. */ + _ux_hcd_sim_host_transaction_schedule(hcd_sim_host, ed); + + } + + /* Point to the next ED in the list. */ + ed = ed -> ux_sim_host_ed_next_ed; + } + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_hcd_sim_host_periodic_tree_create.c b/common/core/src/ux_hcd_sim_host_periodic_tree_create.c new file mode 100644 index 0000000..87669a6 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_periodic_tree_create.c @@ -0,0 +1,138 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_periodic_tree_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates the periodic static tree for the interrupt */ +/* and isochronous EDs. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_ed_obtain Obtain host ED */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_periodic_tree_create(UX_HCD_SIM_HOST *hcd_sim_host) +{ + +UX_HCD_SIM_HOST_ED *ed; +UINT list_index; +UINT list_entries; +UINT current_list_entry; +UX_HCD_SIM_HOST_ED *ed_list[32]; +UX_HCD_SIM_HOST_ED *ed_start_list[32]; + + + /* Start with the 1st list - it has 32 entries. */ + list_entries = 32; + + /* Create each list one by one starting from the 32ms list. */ + for (list_index = 0; list_index < 6; list_index++) + { + + for (current_list_entry = 0; current_list_entry < list_entries; current_list_entry++) + { + + /* In each list, insert an static ED as the anchor. There should not + be any errors when obtaining a new ED, still we do a sanity check. */ + ed = _ux_hcd_sim_host_ed_obtain(hcd_sim_host); + if (ed == UX_NULL) + return(UX_NO_ED_AVAILABLE); + + /* Mark this anchor ED as static by putting it as SKIPPED, the host simulator controller will + not look into its tail and head list and will simply jump to the next ED. */ + ed -> ux_sim_host_ed_status = UX_HCD_SIM_HOST_ED_STATIC; + + /* Either we hook this new ED to the start list for further processing + or we hook it to the 2 successive entries in the previous list. */ + if (list_index == 0) + { + + ed_start_list[current_list_entry] = ed; + } + else + { + + ed_list[current_list_entry * 2] -> ux_sim_host_ed_next_ed = ed; + ed_list[(current_list_entry * 2) + 1] -> ux_sim_host_ed_next_ed = ed; + } + + /* Memorize this ED in the local list. We do this operation now, otherwise + we would erase the previous list EDs. */ + ed_list[current_list_entry] = ed; + } + + /* Shift the number of entries in the next list by 1 (i.e. divide by 2). */ + list_entries = list_entries >> 1; + } + + /* The tree has been completed but the entries in the interrupt list are in the wrong order. + We need to swap each entry according to the host simulator specified entry order list + so that we have a fair interval frequency for each periodic ED. The primary EDs are + fetched from the start list, and stored in the interrupt list. */ + for (current_list_entry = 0; current_list_entry < 32; current_list_entry++) + { + + ed = ed_start_list[_ux_system_host_hcd_periodic_tree_entries[current_list_entry]]; + hcd_sim_host -> ux_hcd_sim_host_interrupt_ed_list[current_list_entry] = ed; + } + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_port_reset.c b/common/core/src/ux_hcd_sim_host_port_reset.c new file mode 100644 index 0000000..6974740 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_port_reset.c @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" +#include "ux_dcd_sim_slave.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_port_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Implements the PORT_RESET request. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* port_index Port index to reset */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_disconnect Simulate device disconnection */ +/* _ux_dcd_sim_slave_initialize_complete Complete device initialization*/ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_port_reset(UX_HCD_SIM_HOST *hcd_sim_host, ULONG port_index) +{ + +UX_SLAVE_DEVICE *device; + + UX_PARAMETER_NOT_USED(hcd_sim_host); + UX_PARAMETER_NOT_USED(port_index); + + /* Get a pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Is this a connection? */ + if (device -> ux_slave_device_state == UX_DEVICE_RESET) + + /* Complete the device initialization. Note that everytime the device + is disconnected, this must be called again for connection. */ + _ux_dcd_sim_slave_initialize_complete(); + + else + { + + /* Host sent a PORT_RESET when the device is Attached, Addressed, or + Configured. Per the USB spec, we should go back to the default state. + We do this by 1) simulating disconnect to get rid of class and device + resources and 2) recreating necessary entities for control transfers. */ + _ux_device_stack_disconnect(); + _ux_dcd_sim_slave_initialize_complete(); + } + + /* In either case, mark the device as default/attached now. */ + device -> ux_slave_device_state = UX_DEVICE_ATTACHED; + + /* This function should never fail. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_port_status_get.c b/common/core/src/ux_hcd_sim_host_port_status_get.c new file mode 100644 index 0000000..50555f3 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_port_status_get.c @@ -0,0 +1,125 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_port_status_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will return the status for each port attached to the */ +/* root HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* port_index Port index */ +/* */ +/* OUTPUT */ +/* */ +/* Host Simulator Port Status */ +/* */ +/* Where port status has the following format: */ +/* */ +/* bit 0 device connection status */ +/* if 0 : no device connected */ +/* if 1 : device connected to the port */ +/* bit 1 port enable status */ +/* if 0 : port disabled */ +/* if 1 : port enabled */ +/* bit 2 port suspend status */ +/* if 0 : port is not suspended */ +/* if 1 : port is suspended */ +/* bit 3 port overcurrent status */ +/* if 0 : port has no overcurrent condition */ +/* if 1 : port has overcurrent condition */ +/* bit 4 port reset status */ +/* if 0 : port is not in reset */ +/* if 1 : port is in reset */ +/* bit 5 port power status */ +/* if 0 : port power is off */ +/* if 1 : port power is on */ +/* bit 6-7 device attached speed */ +/* if 00 : low speed device attached */ +/* if 01 : full speed device attached */ +/* if 10 : high speed device attached */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_hcd_sim_host_port_status_get(UX_HCD_SIM_HOST *hcd_sim_host, ULONG port_index) +{ + +ULONG port_status; + + + /* Check to see if this port is valid on this controller. */ + if (hcd_sim_host -> ux_hcd_sim_host_nb_root_hubs < port_index) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_INDEX_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_INDEX_UNKNOWN, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_PORT_INDEX_UNKNOWN); + } + + /* The port is valid, build the status mask for this port. This function + returns always returned a device connected. */ + port_status = UX_PS_CCS; + + /* And this is a Full speed device. */ + port_status |= UX_PS_DS_FS; + + /* Return port status. */ + return(port_status); +} + diff --git a/common/core/src/ux_hcd_sim_host_regular_td_obtain.c b/common/core/src/ux_hcd_sim_host_regular_td_obtain.c new file mode 100644 index 0000000..ade397e --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_regular_td_obtain.c @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_regular_td_obtain PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains a free TD from the regular TD list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* */ +/* OUTPUT */ +/* */ +/* UX_HCD_SIM_HOST_TD * Pointer to host TD */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_set Set memory block */ +/* _ux_utility_mutex_on Get mutex protection */ +/* _ux_utility_mutex_off Release mutex protection */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_HCD_SIM_HOST_TD *_ux_hcd_sim_host_regular_td_obtain(UX_HCD_SIM_HOST *hcd_sim_host) +{ + +UX_HCD_SIM_HOST_TD *td; +ULONG td_index; + + + /* Get the mutex as this is a critical section. */ + _ux_utility_mutex_on(&_ux_system -> ux_system_mutex); + + /* Start the search from the beginning of the list. */ + td = hcd_sim_host -> ux_hcd_sim_host_td_list; + + for (td_index = 0; td_index < _ux_system_host -> ux_system_host_max_td; td_index++) + { + + /* Check the TD status, a free TD is marked with the UNUSED flag. */ + if (td -> ux_sim_host_td_status == UX_UNUSED) + { + + /* The TD may have been used, so we reset all fields. */ + _ux_utility_memory_set(td, 0, sizeof(UX_HCD_SIM_HOST_TD)); + + /* This TD is now marked as USED. */ + td -> ux_sim_host_td_status = UX_USED; + + /* Release the mutex protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* Return the TD pointer. */ + return(td); + } + + /* Move to next TD. */ + td++; + } + + /* There is no available TD in the TD list. */ + + /* Release the mutex protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* Return a NULL pointer. */ + return(UX_NULL); +} + diff --git a/common/core/src/ux_hcd_sim_host_request_bulk_transfer.c b/common/core/src/ux_hcd_sim_host_request_bulk_transfer.c new file mode 100644 index 0000000..28c72aa --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_request_bulk_transfer.c @@ -0,0 +1,219 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_request_bulk_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a bulk transfer request. A bulk transfer */ +/* can be larger than the size of the sim_host buffer so it may be */ +/* required to chain multiple TDs to accommodate this transfer */ +/* request. A bulk transfer is non blocking, so we return before the */ +/* transfer request is completed. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_regular_td_obtain Obtain regular TD */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_request_bulk_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_HCD_SIM_HOST_TD *data_td; +UX_HCD_SIM_HOST_TD *start_data_td; +UX_HCD_SIM_HOST_TD *next_data_td; +UX_HCD_SIM_HOST_TD *previous_td; +UX_HCD_SIM_HOST_TD *tail_td; +UX_HCD_SIM_HOST_ED *ed; +ULONG transfer_request_payload_length; +ULONG bulk_packet_payload_length; +UCHAR * data_pointer; + + + /* Get the pointer to the Endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* Now get the physical ED attached to this endpoint. */ + ed = endpoint -> ux_endpoint_ed; + + /* Use the TD pointer by ed -> tail for the first TD of this transfer + and chain from this one on. */ + data_td = ed -> ux_sim_host_ed_tail_td; + previous_td = data_td; + + /* Reset the first obtained data TD in case there is a TD shortage while building + the list of TDs. */ + start_data_td = 0; + + /* It may take more than one TD if the transfer_request length is more than the + maximum length for a host simulator TD (this is irrelevant of the MaxPacketSize value + in the endpoint descriptor). Host simulator data payload has a maximum size of 4K. */ + transfer_request_payload_length = transfer_request -> ux_transfer_request_requested_length; + data_pointer = transfer_request -> ux_transfer_request_data_pointer; + + while (transfer_request_payload_length != 0) + { + + if (transfer_request_payload_length > UX_HCD_SIM_HOST_MAX_PAYLOAD) + + bulk_packet_payload_length = UX_HCD_SIM_HOST_MAX_PAYLOAD; + else + + bulk_packet_payload_length = transfer_request_payload_length; + + /* Store the beginning of the buffer address in the TD. */ + data_td -> ux_sim_host_td_buffer = data_pointer; + + /* Update the length of the transfer for this TD. */ + data_td -> ux_sim_host_td_length = bulk_packet_payload_length; + + /* Attach the endpoint and transfer_request to the TD. */ + data_td -> ux_sim_host_td_transfer_request = transfer_request; + data_td -> ux_sim_host_td_ed = ed; + + /* Adjust the data payload length and the data payload pointer. */ + transfer_request_payload_length -= bulk_packet_payload_length; + data_pointer += bulk_packet_payload_length; + + /* The direction of the transaction is set in the TD. */ + if ((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + + data_td -> ux_sim_host_td_direction = UX_HCD_SIM_HOST_TD_IN; + else + data_td -> ux_sim_host_td_direction = UX_HCD_SIM_HOST_TD_OUT; + + /* Mark the TD with the DATA phase. */ + data_td -> ux_sim_host_td_status |= UX_HCD_SIM_HOST_TD_DATA_PHASE; + + /* The Toggle value is in the ED. */ + data_td -> ux_sim_host_td_toggle = UX_HCD_SIM_HOST_TD_TOGGLE_FROM_ED; + + /* Check if there will be another transaction. */ + if (transfer_request_payload_length != 0) + { + + /* Get a new TD to hook this payload. */ + data_td = _ux_hcd_sim_host_regular_td_obtain(hcd_sim_host); + if (data_td == UX_NULL) + { + + /* If there was already a TD chain in progress, free it. */ + if (start_data_td != UX_NULL) + { + + data_td = start_data_td; + while (data_td) + { + + next_data_td = data_td -> ux_sim_host_td_next_td; + data_td -> ux_sim_host_td_status = UX_UNUSED; + data_td = next_data_td; + } + } + + return(UX_NO_TD_AVAILABLE); + } + + /* the first obtained TD in the chain has to be remembered. */ + if (start_data_td == UX_NULL) + start_data_td = data_td; + + /* Attach this new TD to the previous one. */ + previous_td -> ux_sim_host_td_next_td = data_td; + previous_td -> ux_sim_host_td_next_td_transfer_request = data_td; + previous_td = data_td; + } + } + + /* At this stage, the Head and Tail in the ED are still the same and the host simulator + controller will skip this ED until we have hooked the new tail TD. */ + tail_td = _ux_hcd_sim_host_regular_td_obtain(hcd_sim_host); + if (tail_td == UX_NULL) + { + + /* If there was already a TD chain in progress, free it. */ + if (start_data_td != UX_NULL) + { + + data_td = start_data_td; + while (data_td) + { + + next_data_td = data_td -> ux_sim_host_td_next_td; + data_td -> ux_sim_host_td_status = UX_UNUSED; + data_td = next_data_td; + } + } + + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the tail TD to the last data TD. */ + data_td -> ux_sim_host_td_next_td = tail_td; + + /* Store the new tail TD. */ + ed -> ux_sim_host_ed_tail_td = tail_td; + + /* Now we can tell the scheduler to wake up. */ + hcd_sim_host -> ux_hcd_sim_host_queue_empty = UX_FALSE; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_request_control_transfer.c b/common/core/src/ux_hcd_sim_host_request_control_transfer.c new file mode 100644 index 0000000..9e0a2e0 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_request_control_transfer.c @@ -0,0 +1,321 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_request_control_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a control transfer from a transfer request. */ +/* The USB control transfer is in 3 phases (setup, data, status). */ +/* This function will chain all phases of the control sequence before */ +/* setting the sim_host endpoint as a candidate for transfer. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_regular_td_obtain Obtain regular TD */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_short_put Write 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_request_control_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UCHAR *setup_request; +UX_HCD_SIM_HOST_ED *ed; +UX_HCD_SIM_HOST_TD *setup_td; +UX_HCD_SIM_HOST_TD *chain_td; +UX_HCD_SIM_HOST_TD *data_td; +UX_HCD_SIM_HOST_TD *tail_td; +UX_HCD_SIM_HOST_TD *status_td; +UX_HCD_SIM_HOST_TD *start_data_td; +UX_HCD_SIM_HOST_TD *next_data_td; +UINT status; +ULONG transfer_request_payload_length; +ULONG control_packet_payload_length; +UCHAR *data_pointer; + + + /* Get the pointer to the endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* Now get the physical ED attached to this endpoint. */ + ed = endpoint -> ux_endpoint_ed; + + /* Build the SETUP packet (phase 1 of the control transfer). */ + setup_request = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_SETUP_SIZE); + if (setup_request == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + *setup_request = (UCHAR)transfer_request -> ux_transfer_request_function; + *(setup_request + UX_SETUP_REQUEST_TYPE) = (UCHAR)transfer_request -> ux_transfer_request_type; + *(setup_request + UX_SETUP_REQUEST) = (UCHAR)transfer_request -> ux_transfer_request_function; + _ux_utility_short_put(setup_request + UX_SETUP_VALUE, (USHORT)transfer_request -> ux_transfer_request_value); + _ux_utility_short_put(setup_request + UX_SETUP_INDEX, (USHORT)transfer_request -> ux_transfer_request_index); + _ux_utility_short_put(setup_request + UX_SETUP_LENGTH, (USHORT) transfer_request -> ux_transfer_request_requested_length); + + /* Use the TD pointer by ed -> tail for our setup TD and chain from this one on. */ + setup_td = ed -> ux_sim_host_ed_tail_td; + setup_td -> ux_sim_host_td_buffer = setup_request; + setup_td -> ux_sim_host_td_length = UX_SETUP_SIZE; + chain_td = setup_td; + + /* Attach the endpoint and transfer_request to the TD. */ + setup_td -> ux_sim_host_td_transfer_request = transfer_request; + setup_td -> ux_sim_host_td_ed = ed; + + /* Setup is OUT. */ + setup_td -> ux_sim_host_td_direction = UX_HCD_SIM_HOST_TD_OUT; + + /* Mark TD toggle as being DATA0. */ + setup_td -> ux_sim_host_td_toggle = 0; + + /* Mark the TD with the SETUP phase. */ + setup_td -> ux_sim_host_td_status |= UX_HCD_SIM_HOST_TD_SETUP_PHASE; + + /* Check if there is a data phase, if not jump to status phase. */ + data_td = UX_NULL; + start_data_td = UX_NULL; + + /* Use local variables to manipulate data pointer and length. */ + transfer_request_payload_length = transfer_request -> ux_transfer_request_requested_length; + data_pointer = transfer_request -> ux_transfer_request_data_pointer; + + /* Data starts with DATA1. For the data phase, we use the ED to contain the toggle. */ + ed -> ux_sim_host_ed_toggle = 1; + + /* The Control data payload may be split into several smaller blocks. */ + while (transfer_request_payload_length != 0) + { + + /* Get a new TD to hook this payload. */ + data_td = _ux_hcd_sim_host_regular_td_obtain(hcd_sim_host); + if (data_td == UX_NULL) + { + + /* Free the Setup packet resources. */ + _ux_utility_memory_free(setup_request); + + /* If there was already a TD chain in progress, free it. */ + if (start_data_td != UX_NULL) + { + + data_td = start_data_td; + while (data_td) + { + + next_data_td = data_td -> ux_sim_host_td_next_td; + data_td -> ux_sim_host_td_status = UX_UNUSED; + data_td = next_data_td; + } + } + + return(UX_NO_TD_AVAILABLE); + } + + /* Check the current payload requirement for the max size. */ + if (transfer_request_payload_length > UX_HCD_SIM_HOST_MAX_PAYLOAD) + + control_packet_payload_length = UX_HCD_SIM_HOST_MAX_PAYLOAD; + else + + control_packet_payload_length = transfer_request_payload_length; + + /* Store the beginning of the buffer address in the TD. */ + data_td -> ux_sim_host_td_buffer = data_pointer; + + /* Update the length of the transfer for this TD. */ + data_td -> ux_sim_host_td_length = control_packet_payload_length; + + /* Attach the endpoint and transfer request to the TD. */ + data_td -> ux_sim_host_td_transfer_request = transfer_request; + data_td -> ux_sim_host_td_ed = ed; + + /* Adjust the data payload length and the data payload pointer. */ + transfer_request_payload_length -= control_packet_payload_length; + data_pointer += control_packet_payload_length; + + /* The direction of the transaction is set in the TD. */ + if ((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + + data_td -> ux_sim_host_td_direction = UX_HCD_SIM_HOST_TD_IN; + else + + data_td -> ux_sim_host_td_direction = UX_HCD_SIM_HOST_TD_OUT; + + /* Mark the TD with the DATA phase. */ + data_td -> ux_sim_host_td_status |= UX_HCD_SIM_HOST_TD_DATA_PHASE; + + /* The Toggle value is in the ED. */ + data_td -> ux_sim_host_td_toggle = UX_HCD_SIM_HOST_TD_TOGGLE_FROM_ED; + + /* The first obtained TD in the chain has to be remembered. */ + if (start_data_td == UX_NULL) + start_data_td = data_td; + + /* Attach this new TD to the previous one. */ + chain_td -> ux_sim_host_td_next_td = data_td; + chain_td -> ux_sim_host_td_next_td_transfer_request = data_td; + chain_td = data_td; + } + + /* Now, program the status phase. */ + status_td = _ux_hcd_sim_host_regular_td_obtain(hcd_sim_host); + + if (status_td == UX_NULL) + { + + _ux_utility_memory_free(setup_request); + if (data_td != UX_NULL) + { + + data_td = start_data_td; + while (data_td) + { + + next_data_td = data_td -> ux_sim_host_td_next_td; + data_td -> ux_sim_host_td_status = UX_UNUSED; + data_td = next_data_td; + } + } + + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the endpoint and transfer request to the TD. */ + status_td -> ux_sim_host_td_transfer_request = transfer_request; + status_td -> ux_sim_host_td_ed = ed; + + /* Mark the TD with the STATUS phase. */ + status_td -> ux_sim_host_td_status |= UX_HCD_SIM_HOST_TD_STATUS_PHASE; + + /* The direction of the status phase is IN if data phase is OUT and + vice versa. */ + if ((transfer_request -> ux_transfer_request_type&UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + + status_td -> ux_sim_host_td_direction = UX_HCD_SIM_HOST_TD_OUT; + else + + status_td -> ux_sim_host_td_direction = UX_HCD_SIM_HOST_TD_IN; + + /* No data payload for the status phase. */ + status_td -> ux_sim_host_td_buffer = 0; + status_td -> ux_sim_host_td_length = 0; + + /* Status Phase toggle is ALWAYS 1. */ + status_td -> ux_sim_host_td_toggle = 1; + + /* Hook the status phase to the previous TD. */ + chain_td -> ux_sim_host_td_next_td = status_td; + + /* Since we have consumed out tail TD for the setup packet, we must get another one + and hook it to the ED's tail. */ + tail_td = _ux_hcd_sim_host_regular_td_obtain(hcd_sim_host); + if (tail_td == UX_NULL) + { + + _ux_utility_memory_free(setup_request); + if (data_td != UX_NULL) + data_td -> ux_sim_host_td_status = UX_UNUSED; + status_td -> ux_sim_host_td_status = UX_UNUSED; + return(UX_NO_TD_AVAILABLE); + } + + /* Hook the new TD to the status TD. */ + status_td -> ux_sim_host_td_next_td = tail_td; + + /* At this stage, the Head and Tail in the ED are still the same and + the host simulator controller will skip this ED until we have hooked the new + tail TD. */ + ed -> ux_sim_host_ed_tail_td = tail_td; + + /* Now we can tell the scheduler to wake up. */ + hcd_sim_host -> ux_hcd_sim_host_queue_empty = UX_FALSE; + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_CONTROL_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* There was an error, return to the caller. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + } + + /* Free the resources. */ + _ux_utility_memory_free(setup_request); + + /* Return completion to caller. */ + return(transfer_request -> ux_transfer_request_completion_code); +} + diff --git a/common/core/src/ux_hcd_sim_host_request_interupt_transfer.c b/common/core/src/ux_hcd_sim_host_request_interupt_transfer.c new file mode 100644 index 0000000..02ab430 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_request_interupt_transfer.c @@ -0,0 +1,135 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_request_interrupt_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs an interrupt transfer request. An interrupt */ +/* transfer can only be as large as the Maxpacket Field in the */ +/* endpoint descriptor. This was verified at the USB layer and does */ +/* not need to be reverified here. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_regular_td_obtain Obtain regular TD */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_request_interrupt_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_HCD_SIM_HOST_ED *ed; +UX_HCD_SIM_HOST_TD *data_td; +UX_HCD_SIM_HOST_TD *tail_td; + + + /* Get the pointer to the Endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* Now get the physical ED attached to this endpoint. */ + ed = endpoint -> ux_endpoint_ed; + + /* Use the TD pointer by ed -> tail for the first TD of this transfer + and chain from this one on. */ + data_td = ed -> ux_sim_host_ed_tail_td; + + /* Set the direction of the transfer. */ + if ((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + data_td -> ux_sim_host_td_direction = UX_HCD_SIM_HOST_TD_IN; + else + data_td -> ux_sim_host_td_direction = UX_HCD_SIM_HOST_TD_OUT; + + /* Mark the TD with the DATA phase. */ + data_td -> ux_sim_host_td_status |= UX_HCD_SIM_HOST_TD_DATA_PHASE; + + /* The Toggle value is in the ED. */ + data_td -> ux_sim_host_td_toggle = UX_HCD_SIM_HOST_TD_TOGGLE_FROM_ED; + + /* Store the beginning of the buffer address in the TD. */ + data_td -> ux_sim_host_td_buffer = transfer_request -> ux_transfer_request_data_pointer; + + /* Update the length of the transfer for this TD. */ + data_td -> ux_sim_host_td_length = transfer_request -> ux_transfer_request_requested_length; + + /* Attach the endpoint and transfer request to the TD. */ + data_td -> ux_sim_host_td_transfer_request = transfer_request; + data_td -> ux_sim_host_td_ed = ed; + + /* At this stage, the Head and Tail in the ED are still the same and + the host simulator controller will skip this ED until we have hooked the new + tail TD. */ + tail_td = _ux_hcd_sim_host_regular_td_obtain(hcd_sim_host); + if (tail_td == UX_NULL) + return(UX_NO_TD_AVAILABLE); + + /* Attach the tail TD to the last data TD. */ + data_td -> ux_sim_host_td_next_td = tail_td; + + /* Store the new tail TD. */ + ed -> ux_sim_host_ed_tail_td = tail_td; + + /* Now we can tell the scheduler to wake up. */ + hcd_sim_host -> ux_hcd_sim_host_queue_empty = UX_FALSE; + + /* There is no need to wake up the sim_host controller on this transfer + since periodic transactions will be picked up when the interrupt + tree is scanned. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_request_isochronous_transfer.c b/common/core/src/ux_hcd_sim_host_request_isochronous_transfer.c new file mode 100644 index 0000000..fd037ce --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_request_isochronous_transfer.c @@ -0,0 +1,230 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_request_isochronous_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs an isochronous transfer request. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_frame_number_get Get frame number */ +/* _ux_hcd_sim_host_isochronous_td_obtain Obtain isochronous TD */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_request_isochronous_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_HCD_SIM_HOST_ISO_TD *data_td; +UX_HCD_SIM_HOST_ISO_TD *start_data_td; +UX_HCD_SIM_HOST_ISO_TD *next_data_td; +UX_HCD_SIM_HOST_ISO_TD *previous_td; +UX_HCD_SIM_HOST_ISO_TD *tail_td; +UX_HCD_SIM_HOST_ED *ed; +ULONG transfer_request_payload_length; +ULONG isoch_packet_payload_length; +UCHAR * data_pointer; +ULONG current_frame_number; + + + /* Get the pointer to the Endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* Now get the physical ED attached to this endpoint. */ + ed = endpoint -> ux_endpoint_ed; + + /* If the transfer_request specifies a max packet length other than the endpoint + size, we force the transfer request value into the endpoint. */ + if (transfer_request -> ux_transfer_request_packet_length == 0) + transfer_request -> ux_transfer_request_packet_length = (ULONG) endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + + /* Remember the packet length. */ + isoch_packet_payload_length = transfer_request -> ux_transfer_request_packet_length; + + /* Use the TD pointer by ed -> tail for the first TD of this transfer and chain from this one on. */ + data_td = (UX_HCD_SIM_HOST_ISO_TD *) ((void *) ed -> ux_sim_host_ed_tail_td); + previous_td = data_td; + + /* Reset the first obtained data TD in case there is a TD shortage while building the list of TDs. */ + start_data_td = UX_NULL; + + /* Calculate the frame number to be used to send this payload. If there are no current transfers, + we take the current frame number and add a safety value (2-5) to it. If here is pending transactions, + we use the frame number stored in the transfer request. */ + if (ed -> ux_sim_host_ed_tail_td == ed -> ux_sim_host_ed_head_td) + { + + _ux_hcd_sim_host_frame_number_get(hcd_sim_host, ¤t_frame_number); + ed -> ux_sim_host_ed_frame = current_frame_number + UX_HCD_SIM_HOST_FRAME_DELAY; + } + else + { + + current_frame_number = ed -> ux_sim_host_ed_frame; + } + + /* Load the start buffer address and URB length to split the URB in multiple TD transfer. */ + transfer_request_payload_length = transfer_request -> ux_transfer_request_requested_length; + data_pointer = transfer_request -> ux_transfer_request_data_pointer; + + while (transfer_request_payload_length != 0) + { + + /* Set the direction of the TD. */ + if ((transfer_request -> ux_transfer_request_type&UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + + data_td -> ux_sim_host_iso_td_direction = UX_HCD_SIM_HOST_TD_IN; + else + + data_td -> ux_sim_host_iso_td_direction = UX_HCD_SIM_HOST_TD_OUT; + + /* Set the frame number. */ + ed -> ux_sim_host_ed_frame = current_frame_number; + + /* Set the buffer address. */ + data_td -> ux_sim_host_iso_td_buffer = data_pointer; + + /* Update the length of the transfer for this TD. */ + data_td -> ux_sim_host_iso_td_length = isoch_packet_payload_length; + + /* Attach the endpoint and transfer request to the TD. */ + data_td -> ux_sim_host_iso_td_transfer_request = transfer_request; + data_td -> ux_sim_host_iso_td_ed = ed; + + /* Adjust the data payload length and the data payload pointer. */ + transfer_request_payload_length -= isoch_packet_payload_length; + data_pointer += isoch_packet_payload_length; + + /* Prepare the next frame for the next TD in advance. */ + current_frame_number++; + + /* Check if there will be another transaction. */ + if (transfer_request_payload_length != 0) + { + + /* Get a new TD to hook this payload. */ + data_td = _ux_hcd_sim_host_isochronous_td_obtain(hcd_sim_host); + if (data_td == UX_NULL) + { + + /* If there was already a TD chain in progress, free it. */ + if (start_data_td != UX_NULL) + { + + data_td = start_data_td; + while(data_td) + { + + next_data_td = data_td -> ux_sim_host_iso_td_next_td; + data_td -> ux_sim_host_iso_td_status = UX_UNUSED; + data_td = next_data_td; + } + } + + return(UX_NO_TD_AVAILABLE); + } + + /* the first obtained TD in the chain has to be remembered. */ + if (start_data_td == UX_NULL) + start_data_td = data_td; + + /* Attach this new TD to the previous one. */ + previous_td -> ux_sim_host_iso_td_next_td = data_td; + previous_td = data_td; + } + } + + /* Memorize the next frame number for this ED. */ + ed -> ux_sim_host_ed_frame = current_frame_number; + + /* At this stage, the Head and Tail in the ED are still the same and the host simulator controller + will skip this ED until we have hooked the new tail TD. */ + tail_td = _ux_hcd_sim_host_isochronous_td_obtain(hcd_sim_host); + if (tail_td == UX_NULL) + { + + /* If there was already a TD chain in progress, free it. */ + if (start_data_td != UX_NULL) + { + + data_td = start_data_td; + while(data_td) + { + + next_data_td = data_td -> ux_sim_host_iso_td_next_td; + data_td -> ux_sim_host_iso_td_status = UX_UNUSED; + data_td = next_data_td; + } + } + + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the tail TD to the last data TD. */ + data_td -> ux_sim_host_iso_td_next_td = tail_td; + + /* Adjust the ED tail pointer, the controller can now start this transfer + at the chosen frame number. */ + ed -> ux_sim_host_ed_tail_td = (UX_HCD_SIM_HOST_TD *) ((void *) tail_td); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_request_transfer.c b/common/core/src/ux_hcd_sim_host_request_transfer.c new file mode 100644 index 0000000..827856b --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_request_transfer.c @@ -0,0 +1,124 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_request_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the handler for all the transactions on the USB. */ +/* The transfer request passed as parameter contains the endpoint and */ +/* the device descriptors in addition to the type of transaction de */ +/* be executed. This function routes the transfer request to */ +/* according to the type of transfer to be executed. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_sim_host_request_bulk_transfer Request bulk transfer */ +/* _ux_hcd_sim_host_request_control_transfer Request control */ +/* transfer */ +/* _ux_hcd_sim_host_request_interrupt_transfer Request interrupt */ +/* transfer */ +/* _ux_hcd_sim_host_request_isochronous_transfer Request isochronous */ +/* transfer */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_request_transfer(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UINT status = 0; + + + /* Get the pointer to the Endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* We reset the actual length field of the transfer request as a safety measure. */ + transfer_request -> ux_transfer_request_actual_length = 0; + + /* Isolate the endpoint type and route the transfer request. */ + switch ((endpoint -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + + status = _ux_hcd_sim_host_request_control_transfer(hcd_sim_host, transfer_request); + break; + + + case UX_BULK_ENDPOINT: + + status = _ux_hcd_sim_host_request_bulk_transfer(hcd_sim_host, transfer_request); + break; + + case UX_INTERRUPT_ENDPOINT: + + status = _ux_hcd_sim_host_request_interrupt_transfer(hcd_sim_host, transfer_request); + break; + + case UX_ISOCHRONOUS_ENDPOINT: + + status = _ux_hcd_sim_host_request_isochronous_transfer(hcd_sim_host, transfer_request); + break; + + } + + /* Note that it is physically impossible to have a wrong endpoint type here + so no error checking. */ + return(status); +} + diff --git a/common/core/src/ux_hcd_sim_host_timer_function.c b/common/core/src/ux_hcd_sim_host_timer_function.c new file mode 100644 index 0000000..f65e0c0 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_timer_function.c @@ -0,0 +1,97 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" +#include "tx_timer.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_timer_function PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the timer function of the simulator. It is */ +/* invoked on a timer every tick. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host_addr Address of host controller */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_semaphore_put Put semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_sim_host_timer_function(ULONG hcd_sim_host_addr) +{ + +UX_HCD_SIM_HOST *hcd_sim_host; +UX_HCD *hcd; + + + /* Setup pointer to simulator host structure. */ + UX_TIMER_EXTENSION_PTR_GET(hcd_sim_host, UX_HCD_SIM_HOST, hcd_sim_host_addr) + + /* Get the pointers to the generic HCD areas. */ + hcd = hcd_sim_host -> ux_hcd_sim_host_hcd_owner; + + /* Increase the interrupt count. This indicates the controller is still alive. */ + hcd_sim_host -> ux_hcd_sim_host_interrupt_count++; + + /* Check if the controller is operational, if not, skip it. */ + if (hcd -> ux_hcd_status == UX_HCD_STATUS_OPERATIONAL) + { + + /* Wake up the thread for the controller transaction processing. */ + hcd -> ux_hcd_thread_signal++; + _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + } +} + + diff --git a/common/core/src/ux_hcd_sim_host_transaction_schedule.c b/common/core/src/ux_hcd_sim_host_transaction_schedule.c new file mode 100644 index 0000000..af75c68 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_transaction_schedule.c @@ -0,0 +1,495 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" +#include "ux_dcd_sim_slave.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_transaction_schedule PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function bridges a transaction from the host to the slave */ +/* simulation controller. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* ed Pointer to ED */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_transfer_request_completion_function) */ +/* Completion function */ +/* _ux_device_stack_control_request_process */ +/* Process request */ +/* _ux_utility_memory_copy Copy memory block */ +/* _ux_utility_semaphore_put Semaphore put */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_transaction_schedule(UX_HCD_SIM_HOST *hcd_sim_host, UX_HCD_SIM_HOST_ED *ed) +{ + +UX_DCD_SIM_SLAVE *dcd_sim_slave; +UX_HCD_SIM_HOST_TD *td; +UX_HCD_SIM_HOST_TD *head_td; +UX_HCD_SIM_HOST_TD *tail_td; +UX_HCD_SIM_HOST_TD *data_td; +UX_ENDPOINT *endpoint; +UX_SLAVE_ENDPOINT *slave_endpoint; +UX_DCD_SIM_SLAVE_ED *slave_ed; +ULONG slave_transfer_remaining; +UCHAR wake_host; +UCHAR wake_slave; +ULONG transaction_length; +UX_SLAVE_TRANSFER *slave_transfer_request; +UX_TRANSFER *transfer_request; +ULONG endpoint_index; +UX_SLAVE_DCD *dcd; + + UX_PARAMETER_NOT_USED(hcd_sim_host); + + /* Get the pointer to the DCD portion of the simulator. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Check the state of the controller if OPERATIONAL . */ + if (dcd -> ux_slave_dcd_status != UX_DCD_STATUS_OPERATIONAL) + return(UX_ERROR); + + /* Get the pointer to the candidate TD on the host. */ + td = ed -> ux_sim_host_ed_head_td; + + /* Get the pointer to the endpoint. */ + endpoint = ed -> ux_sim_host_ed_endpoint; + + /* Get the pointer to the transfer_request attached with this TD. */ + transfer_request = td -> ux_sim_host_td_transfer_request; + + /* Get the index of the endpoint from the host. */ + endpoint_index = endpoint -> ux_endpoint_descriptor.bEndpointAddress & ~(ULONG)UX_ENDPOINT_DIRECTION; + + /* Get the address of the device controller. */ + dcd_sim_slave = (UX_DCD_SIM_SLAVE *) dcd -> ux_slave_dcd_controller_hardware; + + /* Get the endpoint as seen from the device side. */ + slave_ed = &dcd_sim_slave -> ux_dcd_sim_slave_ed[endpoint_index]; + + /* Is this ED used? */ + if ((slave_ed -> ux_sim_slave_ed_status & UX_DCD_SIM_SLAVE_ED_STATUS_USED) == 0) + return(UX_ERROR); + + /* Is this ED ready for transaction or stalled ? */ + if ((slave_ed -> ux_sim_slave_ed_status & (UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER | UX_DCD_SIM_SLAVE_ED_STATUS_STALLED)) == 0) + return(UX_ERROR); + + /* Get the logical endpoint from the physical endpoint. */ + slave_endpoint = slave_ed -> ux_sim_slave_ed_endpoint; + + /* Get the pointer to the transfer request. */ + slave_transfer_request = &slave_endpoint -> ux_slave_endpoint_transfer_request; + + /* Check the phase for this transfer, if this is the SETUP phase, treatment is different. Explanation of how + control transfers are handled in the simulator: if the data phase is OUT, we handle it immediately, meaning we + send all the data to the device and remove the STATUS TD in the same scheduler call. If the data phase is IN, we + only take out the SETUP TD and handle the data phase like any other non-control transactions (i.e. the scheduler + calls us again with the DATA TDs). */ + if (td -> ux_sim_host_td_status & UX_HCD_SIM_HOST_TD_SETUP_PHASE) + { + + /* For control transfer, stall is for protocol error and it's cleared any time when SETUP is received */ + slave_ed -> ux_sim_slave_ed_status &= ~(ULONG)UX_DCD_SIM_SLAVE_ED_STATUS_STALLED; + + /* Set the length to the setup transaction buffer. */ + slave_transfer_request -> ux_slave_transfer_request_actual_length = td -> ux_sim_host_td_length; + + /* Move the buffer from the host TD to the device TD. */ + _ux_utility_memory_copy(slave_transfer_request -> ux_slave_transfer_request_setup, td -> ux_sim_host_td_buffer, + td -> ux_sim_host_td_length); + + /* The setup phase never fails. We acknowledge the transfer code here by taking the TD out of the endpoint. */ + ed -> ux_sim_host_ed_head_td = td -> ux_sim_host_td_next_td; + + /* Free the TD that was used here. */ + td -> ux_sim_host_td_status = UX_UNUSED; + + /* Check if the transaction is OUT from the host and there is data payload. */ + if (((*slave_transfer_request -> ux_slave_transfer_request_setup & UX_REQUEST_IN) == 0) && + (*(slave_transfer_request -> ux_slave_transfer_request_setup + 6) != 0 || + *(slave_transfer_request -> ux_slave_transfer_request_setup + 7) != 0)) + { + + /* This is the case where there is a data payload OUT from host to device. + the data needs to be copied into the device buffer first before invoking the control + dispatcher. */ + + /* Get the length we expect from the SETUP packet. */ + slave_transfer_request -> ux_slave_transfer_request_requested_length = _ux_utility_short_get(slave_transfer_request -> ux_slave_transfer_request_setup + 6); + + /* Reset what we have received so far. */ + slave_transfer_request -> ux_slave_transfer_request_actual_length = 0; + + /* And reprogram the current buffer address to the beginning of the buffer. */ + slave_transfer_request -> ux_slave_transfer_request_current_data_pointer = slave_transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Get the pointer to the first data TD. this is the TD right after the SETUP one. */ + data_td = td -> ux_sim_host_td_next_td; + + /* Get the data length we expect. */ + transaction_length = slave_transfer_request -> ux_slave_transfer_request_requested_length; + + /* It may have taken multiple TDs to send all the data. */ + while (transaction_length != 0) + { + + /* Do a sanity check. TD must be data. */ + if (data_td -> ux_sim_host_td_status & UX_HCD_SIM_HOST_TD_DATA_PHASE) + { + + /* Copy the amount of data in the td into the slave transaction buffer. */ + _ux_utility_memory_copy(slave_transfer_request -> ux_slave_transfer_request_current_data_pointer, data_td -> ux_sim_host_td_buffer, + data_td -> ux_sim_host_td_length); + + /* Add to the actual payload length. */ + slave_transfer_request -> ux_slave_transfer_request_actual_length += data_td -> ux_sim_host_td_length; + + /* Update the host transfer's actual length. */ + transfer_request -> ux_transfer_request_actual_length += transaction_length; + + /* Decrement the total length. */ + transaction_length -= data_td -> ux_sim_host_td_length; + + /* Update buffer pointer. */ + slave_transfer_request -> ux_slave_transfer_request_current_data_pointer += data_td -> ux_sim_host_td_length; + + /* Update the td in the head. */ + ed -> ux_sim_host_ed_head_td = data_td; + + /* Get the pointer to the next data TD. */ + data_td = data_td -> ux_sim_host_td_next_td; + + /* Free the TD that was used here. */ + ed -> ux_sim_host_ed_head_td -> ux_sim_host_td_status = UX_UNUSED; + } + } + + /* Make the head TD point to the STATUS TD. */ + ed -> ux_sim_host_ed_head_td = ed -> ux_sim_host_ed_head_td -> ux_sim_host_td_next_td; + } + + /* Is there no hub? */ + if (dcd_sim_slave -> ux_dcd_sim_slave_dcd_control_request_process_hub == UX_NULL) + { + + /* There's no hub to worry about. This control transfer is for the + device itself. */ + + /* Pass the transfer to the regular device stack. */ + _ux_device_stack_control_request_process(slave_transfer_request); + } + else + { + + /* There is a hub. We need to call the correct Control Transfer dispatcher. + If the device is a hub and this transfer is for one of the devices on the + hub, then we must invoke a separate Control Transfer dispatcher besides + the regular device stack's. This is because the current device stack doesn't + handle control transfers to device's other than itself. */ + + /* Is this meant for the device itself? */ + if (/* If the device isn't ADDRESSED yet, then the address may be invalid since we don't + clear it upon disconnection/reconnection. So we assume that if the device is RESET + or ATTACHED, the control transfer is meant for the device itself. */ + (_ux_system_slave->ux_system_slave_device.ux_slave_device_state == UX_DEVICE_RESET || + _ux_system_slave->ux_system_slave_device.ux_slave_device_state == UX_DEVICE_ATTACHED) || + + /* If we get to this check, then the device has been ADDRESSED and we can compare addresses. */ + endpoint -> ux_endpoint_device -> ux_device_address == dcd -> ux_slave_dcd_device_address) + { + + /* Yes, this control transfer is meant for the device itself. */ + + /* Pass the transfer to the regular device stack. */ + _ux_device_stack_control_request_process(slave_transfer_request); + } + else + { + + /* No, this control transfer is meant for a device on the hub. */ + + /* Pass the transfer to the callback. */ + dcd_sim_slave -> ux_dcd_sim_slave_dcd_control_request_process_hub(slave_transfer_request); + } + } + + /* Check if the transaction is OUT from the host. */ + if ((*slave_transfer_request -> ux_slave_transfer_request_setup & UX_REQUEST_IN) == 0) + { + + /* Check if there is a problem with the endpoint (maybe stalled). */ + if (slave_ed -> ux_sim_slave_ed_status & UX_DCD_SIM_SLAVE_ED_STATUS_STALLED) + { + + /* Protocol error, stall the transaction. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_STALLED; + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_TRANSFER_STALLED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_STALLED, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + } + else + /* No error in simulation. */ + transfer_request -> ux_transfer_request_completion_code = UX_SUCCESS; + + /* In this case the transfer is completed! We take out the status TD. */ + td = ed -> ux_sim_host_ed_head_td; + + /* Adjust the ED. */ + ed -> ux_sim_host_ed_head_td = td -> ux_sim_host_td_next_td; + + /* Free the TD that was used here. */ + td -> ux_sim_host_td_status = UX_UNUSED; + + /* Then, we wake up the host. */ + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + } + } + else + { + + /* Check if there is a problem with the endpoint (maybe stalled). */ + if (slave_ed -> ux_sim_slave_ed_status & UX_DCD_SIM_SLAVE_ED_STATUS_STALLED) + { + + /* Stall the transaction. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_STALLED; + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_TRANSFER_STALLED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_STALLED, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Wake up the host side. */ + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + + /* Clean up this ED. */ + head_td = ed -> ux_sim_host_ed_head_td; + tail_td = ed -> ux_sim_host_ed_tail_td; + + /* Free all TDs attached to the ED. */ + while (head_td != tail_td) + { + + /* Mark the current head TD as free. */ + head_td -> ux_sim_host_td_status = UX_UNUSED; + + /* Update the head TD with the next TD. */ + ed -> ux_sim_host_ed_head_td = head_td -> ux_sim_host_td_next_td; + + /* Now the new head_td is the next TD in the chain. */ + head_td = ed -> ux_sim_host_ed_head_td; + } + } + else + { + + slave_transfer_remaining = 0; + + /* If the device tries to send a NULL packet, we don't reset the actual length to 0. */ + if (slave_transfer_request -> ux_slave_transfer_request_requested_length != 0) + slave_transfer_remaining = slave_transfer_request -> ux_slave_transfer_request_requested_length - slave_transfer_request -> ux_slave_transfer_request_actual_length; + + /* Get the transaction length to be transferred. It could be a ZLP condition. */ + if (slave_transfer_remaining <= td -> ux_sim_host_td_length) + transaction_length = slave_transfer_remaining; + else + transaction_length = td -> ux_sim_host_td_length; + + if (td -> ux_sim_host_td_direction == UX_HCD_SIM_HOST_TD_OUT) + + /* Send the requested host data to the device. */ + _ux_utility_memory_copy(slave_transfer_request -> ux_slave_transfer_request_current_data_pointer, td -> ux_sim_host_td_buffer, + transaction_length); + + else + + /* Send the requested host data to the device. */ + _ux_utility_memory_copy(td -> ux_sim_host_td_buffer, slave_transfer_request -> ux_slave_transfer_request_current_data_pointer, + transaction_length); + + /* Update buffers. */ + td -> ux_sim_host_td_buffer += transaction_length; + slave_transfer_request -> ux_slave_transfer_request_current_data_pointer += transaction_length; + + /* Update actual length values. */ + td -> ux_sim_host_td_actual_length += transaction_length; + transfer_request -> ux_transfer_request_actual_length += transaction_length; + slave_transfer_request -> ux_slave_transfer_request_actual_length += transaction_length; + + /* Update requested length values. */ + td -> ux_sim_host_td_length -= transaction_length; + + /* Are we done with this TD (It's possible for the TD to expect more data; for example, the slave + sent/received a smaller amount)? */ + if (td -> ux_sim_host_td_length == 0) + { + + /* Free the TD that was used here. */ + td -> ux_sim_host_td_status = UX_UNUSED; + + /* Adjust the ED. */ + ed -> ux_sim_host_ed_head_td = td -> ux_sim_host_td_next_td; + } + + /* Reset wake booleans. */ + wake_host = UX_FALSE; + wake_slave = UX_FALSE; + + /* Does the slave have absolutely no more data to send? */ + if ((slave_transfer_request -> ux_slave_transfer_request_actual_length == slave_transfer_request -> ux_slave_transfer_request_requested_length && + slave_transfer_request -> ux_slave_transfer_request_force_zlp == UX_TRUE) || + (transaction_length == 0) || + (transaction_length % slave_endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize)) + { + + wake_host = UX_TRUE; + wake_slave = UX_TRUE; + } + else + { + + /* Is the host's transfer completed? */ + if (transfer_request -> ux_transfer_request_actual_length == transfer_request -> ux_transfer_request_requested_length) + wake_host = UX_TRUE; + + /* Is the slaves's transfer completed? */ + if (slave_transfer_request -> ux_slave_transfer_request_actual_length == slave_transfer_request -> ux_slave_transfer_request_requested_length) + wake_slave = UX_TRUE; + } + + if (wake_slave == UX_TRUE) + { + + /* Set the completion code to no error. */ + slave_transfer_request -> ux_slave_transfer_request_completion_code = UX_SUCCESS; + + /* Set the transfer status to COMPLETED. */ + slave_transfer_request -> ux_slave_transfer_request_status = UX_TRANSFER_STATUS_COMPLETED; + + /* Is this not the control endpoint? */ + if (slave_ed -> ux_sim_slave_ed_index != 0) + { + + /* Reset the ED to NO TRANSFER status. */ + slave_ed -> ux_sim_slave_ed_status &= ~(ULONG)UX_DCD_SIM_SLAVE_ED_STATUS_TRANSFER; + + /* Wake up the slave side. */ + _ux_utility_semaphore_put(&slave_transfer_request -> ux_slave_transfer_request_semaphore); + } + } + + if (wake_host == UX_TRUE) + { + + /* If the slave has less data to send than the host wants to receive, then there may still be + TDs left to free. Note that this should only happen for IN transactions, since the only way + an OUT transfer can complete is if all the data was sent i.e. all the TDs were sent and freed. */ + if (ed -> ux_sim_host_ed_head_td != ed -> ux_sim_host_ed_tail_td) + { + + /* Free all TDs associated with this transfer. Note that if this is a control transfer (which + means it must be IN), then this also gets rid of the STATUS phase, which is okay. Also note + that assumes that there is only one transfer occurring on this endpoint; if there were + multiple, then we'd erase that one's TDs as well. Luckily, with the way USBX is designed, + there should never be multiple transfers occurring simultaneously on a single endpoint + (tldr; data pointer for transfers is shared). */ + head_td = ed -> ux_sim_host_ed_head_td; + while (head_td != ed -> ux_sim_host_ed_tail_td) + { + + /* Free the TD that was used here. */ + head_td -> ux_sim_host_td_status = UX_UNUSED; + + /* Move to the next. */ + head_td = head_td -> ux_sim_host_td_next_td; + } + + /* Update the head and tail TD. */ + ed -> ux_sim_host_ed_head_td = head_td; + ed -> ux_sim_host_ed_tail_td = head_td; + } + + /* Set the completion code to no error. */ + transfer_request -> ux_transfer_request_completion_code = UX_SUCCESS; + + /* Set the transfer status to COMPLETED. */ + transfer_request -> ux_transfer_request_status = UX_TRANSFER_STATUS_COMPLETED; + + /* Is there a callback on the host? */ + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + + /* Wake up the host side. */ + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + } + } + } + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_hcd_sim_host_transfer_abort.c b/common/core/src/ux_hcd_sim_host_transfer_abort.c new file mode 100644 index 0000000..a205018 --- /dev/null +++ b/common/core/src/ux_hcd_sim_host_transfer_abort.c @@ -0,0 +1,131 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Simulator Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_sim_host.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_sim_host_transfer_abort PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will abort transactions attached to a transfer */ +/* request. */ +/* */ +/* INPUT */ +/* */ +/* hcd_sim_host Pointer to host controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_delay_ms Delay */ +/* */ +/* CALLED BY */ +/* */ +/* Host Simulator Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_sim_host_transfer_abort(UX_HCD_SIM_HOST *hcd_sim_host, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_HCD_SIM_HOST_ED *ed; +UX_HCD_SIM_HOST_TD *head_td; +UX_HCD_SIM_HOST_TD *tail_td; + + UX_PARAMETER_NOT_USED(hcd_sim_host); + + /* Get the pointer to the endpoint associated with the transfer request. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* From the endpoint container, get the address of the physical endpoint. */ + ed = (UX_HCD_SIM_HOST_ED *) endpoint -> ux_endpoint_ed; + + /* Check if this physical endpoint has been initialized properly! */ + if (ed == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* The endpoint may be active. If so, set the skip bit. */ + ed -> ux_sim_host_ed_status |= UX_HCD_SIM_HOST_ED_SKIP; + + /* Wait for the controller to finish the current frame processing. */ + _ux_utility_delay_ms(1); + + /* Remove all the TDs from this ED and leave the head and tail pointing to the dummy TD. */ + head_td = ed -> ux_sim_host_ed_head_td; + tail_td = ed -> ux_sim_host_ed_tail_td; + + /* Free all TDs attached to the ED. */ + while (head_td != tail_td) + { + + /* Mark the current head TD as free. */ + head_td -> ux_sim_host_td_status = UX_UNUSED; + + /* Update the head TD with the next TD. */ + ed -> ux_sim_host_ed_head_td = head_td -> ux_sim_host_td_next_td; + + /* Now the new head TD is the next TD in the chain. */ + head_td = ed -> ux_sim_host_ed_head_td; + } + + /* Remove the reset bit in the ED. */ + ed -> ux_sim_host_ed_status = (ULONG)~UX_HCD_SIM_HOST_ED_SKIP; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_class_dpump_activate.c b/common/core/src/ux_host_class_dpump_activate.c new file mode 100644 index 0000000..1a69150 --- /dev/null +++ b/common/core/src/ux_host_class_dpump_activate.c @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_dpump.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_dpump_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to activate the class. */ +/* */ +/* INPUT */ +/* */ +/* command Dpump class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_dpump_configure Configure dpump class */ +/* _ux_host_class_dpump_endpoints_get Get endpoints of dpump */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_semaphore_create Create dpump semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_dpump_entry Entry of dpump class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_dpump_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_INTERFACE *interface; +UX_HOST_CLASS_DPUMP *dpump; +UINT status; + + + /* The data pump is always activated by the interface descriptor and not the + device descriptor. */ + interface = (UX_INTERFACE *) command -> ux_host_class_command_container; + + /* Obtain memory for this class instance. */ + dpump = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS_DPUMP)); + if (dpump == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance. */ + dpump -> ux_host_class_dpump_class = command -> ux_host_class_command_class_ptr; + + /* Store the interface container into the dpump class instance. */ + dpump -> ux_host_class_dpump_interface = interface; + + /* Store the device container into the dpump class instance. */ + dpump -> ux_host_class_dpump_device = interface -> ux_interface_configuration -> ux_configuration_device; + + /* This instance of the device must also be stored in the interface container. */ + interface -> ux_interface_class_instance = (VOID *) dpump; + + /* Create this class instance. */ + status = _ux_host_stack_class_instance_create(dpump -> ux_host_class_dpump_class, (VOID *) dpump); + + /* Configure the dpump. */ + status = _ux_host_class_dpump_configure(dpump); + if (status != UX_SUCCESS) + { + + _ux_host_stack_class_instance_destroy(dpump -> ux_host_class_dpump_class, (VOID *) dpump); + return(status); + } + + /* Get the dpump endpoint(s). We will need to search for Bulk Out and Bulk In endpoints. Do not check for errors + here as the alternate setting for this interface may be 0 which has no endpoints. */ + status = _ux_host_class_dpump_endpoints_get(dpump); + + /* Create the semaphore to protect 2 threads from accessing the same dpump instance. */ + status = _ux_utility_semaphore_create(&dpump -> ux_host_class_dpump_semaphore, "ux_dpump_semaphore", 1); + if (status != UX_SUCCESS) + return(UX_SEMAPHORE_ERROR); + + /* Mark the dpump as live now. */ + dpump -> ux_host_class_dpump_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if ((status == UX_SUCCESS) && (_ux_system_host -> ux_system_host_change_function != UX_NULL)) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, dpump -> ux_host_class_dpump_class, (VOID *) dpump); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_DPUMP_ACTIVATE, dpump, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, dpump, 0, 0, 0) + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_host_class_dpump_configure.c b/common/core/src/ux_host_class_dpump_configure.c new file mode 100644 index 0000000..5b3867d --- /dev/null +++ b/common/core/src/ux_host_class_dpump_configure.c @@ -0,0 +1,143 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_dpump.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_dpump_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to the */ +/* dpump. Once the dpump is configured, its interface will be */ +/* activated. The bulk endpoints enumerated(1 IN, 1 OUT ). */ +/* */ +/* INPUT */ +/* */ +/* dpump Pointer to dpump class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get Get interface */ +/* _ux_host_stack_device_configuration_get Get configuration */ +/* _ux_host_stack_device_configuration_select Select configuration */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_dpump_activate Data Pump class activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_dpump_configure(UX_HOST_CLASS_DPUMP *dpump) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_DEVICE *parent_device; + + + /* If the device has been configured already, we don't need to do it + again. */ + if (dpump -> ux_host_class_dpump_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* A dpump normally has one configuration. So retrieve the 1st configuration + only. */ + status = _ux_host_stack_device_configuration_get(dpump -> ux_host_class_dpump_device, 0, &configuration); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, dpump -> ux_host_class_dpump_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check the dpump power source and check the parent power source for + incompatible connections. */ + if (dpump -> ux_host_class_dpump_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* Get parent device pointer. */ + parent_device = dpump -> ux_host_class_dpump_device -> ux_device_parent; + + /* If the device is NULL, the parent is the root dpump and we don't have to worry + if the parent is not the root dpump, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, dpump, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration. */ + status = _ux_host_stack_device_configuration_select(configuration); + if (status != UX_SUCCESS) + return(status); + + /* If the operation went well, the dpump default alternate setting for the dpump interface is + active and the interrupt endpoint is now enabled. We have to memorize the first interface since + the interrupt endpoint is hooked to it. */ + status = _ux_host_stack_configuration_interface_get(configuration, 0, 0, &dpump -> ux_host_class_dpump_interface); + if (status != UX_SUCCESS) + { + + /* Store the instance in the interface container, this is for the USB stack + when it needs to invoke the class. */ + dpump -> ux_host_class_dpump_interface -> ux_interface_class_instance = (VOID *) dpump; + } + + /* Return completion status. */ + return(status); +} + + diff --git a/common/core/src/ux_host_class_dpump_deactivate.c b/common/core/src/ux_host_class_dpump_deactivate.c new file mode 100644 index 0000000..3fab273 --- /dev/null +++ b/common/core/src/ux_host_class_dpump_deactivate.c @@ -0,0 +1,136 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_dpump.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_dpump_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the dpump has been */ +/* removed from the bus either directly or indirectly. The bulk in\out */ +/* pipes will be destroyed and the instanced removed. */ +/* */ +/* INPUT */ +/* */ +/* command Data Pump class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_utility_thread_sleep Sleep thread */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_dpump_entry Entry of dpump class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_dpump_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_DPUMP *dpump; +UINT status; + + + /* Get the instance for this class. */ + dpump = (UX_HOST_CLASS_DPUMP *) command -> ux_host_class_command_instance; + + /* The dpump is being shut down. */ + dpump -> ux_host_class_dpump_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&dpump -> ux_host_class_dpump_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, dpump, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* We need to abort transactions on the bulk Out pipe. */ + _ux_host_stack_endpoint_transfer_abort(dpump -> ux_host_class_dpump_bulk_out_endpoint); + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(dpump -> ux_host_class_dpump_bulk_in_endpoint); + + /* If the class instance was busy, let it finish properly and not return. */ + _ux_utility_thread_sleep(UX_ENUMERATION_THREAD_WAIT); + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(dpump -> ux_host_class_dpump_class, (VOID *) dpump); + + /* Destroy the semaphore. */ + _ux_utility_semaphore_delete(&dpump -> ux_host_class_dpump_semaphore); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, dpump -> ux_host_class_dpump_class, (VOID *) dpump); + } + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_DPUMP_DEACTIVATE, dpump, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(dpump); + + /* Free the dpump instance memory. */ + _ux_utility_memory_free(dpump); + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_class_dpump_endpoints_get.c b/common/core/src/ux_host_class_dpump_endpoints_get.c new file mode 100644 index 0000000..466c423 --- /dev/null +++ b/common/core/src/ux_host_class_dpump_endpoints_get.c @@ -0,0 +1,163 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_dpump.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_dpump_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function search for the handle of the bulk out and bulk in */ +/* endpoints. */ +/* */ +/* INPUT */ +/* */ +/* dpump Pointer to dpump class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_dpump_activate Activate dpump class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_dpump_endpoints_get(UX_HOST_CLASS_DPUMP *dpump) +{ + +UINT status; +UINT endpoint_index; +UX_ENDPOINT *endpoint; + + + /* Search the bulk OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < dpump -> ux_host_class_dpump_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get interface endpoint. */ + status = _ux_host_stack_interface_endpoint_get(dpump -> ux_host_class_dpump_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the OUT direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + + /* We have found the bulk endpoint, save it. */ + dpump -> ux_host_class_dpump_bulk_out_endpoint = endpoint; + break; + } + } + } + + /* The bulk out endpoint is mandatory. */ + if (dpump -> ux_host_class_dpump_bulk_out_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, dpump, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search the bulk IN endpoint. It is attached to the interface container. */ + + for (endpoint_index = 0; endpoint_index < dpump -> ux_host_class_dpump_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + status = _ux_host_stack_interface_endpoint_get(dpump -> ux_host_class_dpump_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the bulk endpoint, save it. */ + dpump -> ux_host_class_dpump_bulk_in_endpoint = endpoint; + break; + } + } + } + + /* The bulk in endpoint is mandatory. */ + if (dpump -> ux_host_class_dpump_bulk_in_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, dpump, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* All endpoints have been mounted. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_class_dpump_entry.c b/common/core/src/ux_host_class_dpump_entry.c new file mode 100644 index 0000000..6be5385 --- /dev/null +++ b/common/core/src/ux_host_class_dpump_entry.c @@ -0,0 +1,121 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_dpump.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_dpump_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the dpump class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* dpump on the bus or when the USB dpump is removed. */ +/* */ +/* INPUT */ +/* */ +/* command Data pump class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_dpump_activate Activate dpump class */ +/* _ux_host_class_dpump_deactivate Deactivate dpump class */ +/* */ +/* CALLED BY */ +/* */ +/* Data pump Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) && + (command -> ux_host_class_command_class == UX_HOST_CLASS_DPUMP_CLASS) && + (command -> ux_host_class_command_subclass == UX_HOST_CLASS_DPUMP_SUBCLASS) && + (command -> ux_host_class_command_protocol == UX_HOST_CLASS_DPUMP_PROTOCOL)) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_dpump_activate(command); + return(status); + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_dpump_deactivate(command); + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/core/src/ux_host_class_dpump_ioctl.c b/common/core/src/ux_host_class_dpump_ioctl.c new file mode 100644 index 0000000..7e197ea --- /dev/null +++ b/common/core/src/ux_host_class_dpump_ioctl.c @@ -0,0 +1,164 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_dpump.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_dpump_ioctl PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the application to change the alternate */ +/* setting of the dpump class. */ +/* */ +/* INPUT */ +/* */ +/* dpump Pointer to the dpump class */ +/* ioctl_function ioctl function */ +/* parameter pointer to structure */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_setting_select */ +/* Select alternate setting */ +/* */ +/* CALLED BY */ +/* */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_dpump_ioctl(UX_HOST_CLASS_DPUMP *dpump, ULONG ioctl_function, + VOID *parameter) +{ + +UX_CONFIGURATION *configuration; +UX_INTERFACE *interface; +UINT status; + + /* Ensure the instance is valid. */ + if ((dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE) && + (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_MOUNTING)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, dpump, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* The command request will tell us we need to do here. */ + switch (ioctl_function) + { + + case UX_HOST_CLASS_DPUMP_SELECT_ALTERNATE_SETTING: + + + /* The parameter value has the alternate setting number. + We need to scan the entire device framework. Only one configuration for data pump device framework. */ + interface = dpump -> ux_host_class_dpump_interface; + configuration = interface -> ux_interface_configuration; + + /* Do some verification just in case ! */ + if (configuration == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Point to the first interface. */ + interface = configuration -> ux_configuration_first_interface; + + /* Loop on all interfaces and alternate settings for this device in search of the right alternate setting. */ + while (interface != UX_NULL) + { + + /* Check the alternate setting. */ + if (interface -> ux_interface_descriptor.bAlternateSetting == (ULONG) (ALIGN_TYPE) parameter) + { + + /* We have found the alternate setting. Select it now. */ + status = _ux_host_stack_interface_setting_select(interface); + + /* We are done here. */ + return(status); + } + + /* Next interface. */ + interface = interface -> ux_interface_next_interface; + } + + /* We come here when the alternate setting was not found. */ + status = UX_INTERFACE_HANDLE_UNKNOWN; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + + break; + + default: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Function not supported. Return an error. */ + status = UX_FUNCTION_NOT_SUPPORTED; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + + } + + /* Return status to caller. */ + return(status); +} + diff --git a/common/core/src/ux_host_class_dpump_read.c b/common/core/src/ux_host_class_dpump_read.c new file mode 100644 index 0000000..363eb0b --- /dev/null +++ b/common/core/src/ux_host_class_dpump_read.c @@ -0,0 +1,205 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_dpump.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_dpump_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the dpump interface. The call is */ +/* blocking and only returns when there is either an error or when */ +/* the transfer is complete. */ +/* */ +/* INPUT */ +/* */ +/* dpump Pointer to dpump class */ +/* data_pointer Pointer to buffer */ +/* requested_length Requested data read */ +/* actual_length Actual data read */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify the class instance */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_dpump_read(UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_DPUMP_READ, dpump, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_dpump_name, (VOID *) dpump) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, dpump, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&dpump -> ux_host_class_dpump_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* Start by resetting the actual length of the transfer to zero. */ + *actual_length = 0; + + /* Get the pointer to the bulk in endpoint in the transfer_request. */ + transfer_request = &dpump -> ux_host_class_dpump_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Perform a transfer on the bulk in endpoint until either the transfer is + completed or until there is an error. */ + while (requested_length) + { + + /* Program the maximum authorized length for this transfer request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer_request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_DPUMP_CLASS_TRANSFER_TIMEOUT); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer request in case some data was actually received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + + /* There was a non transfer error, no partial transfer to be checked. */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually received and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + + /* Return success to caller. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to receive. */ + requested_length -= transfer_request_length; + } + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_class_dpump_write.c b/common/core/src/ux_host_class_dpump_write.c new file mode 100644 index 0000000..ceba568 --- /dev/null +++ b/common/core/src/ux_host_class_dpump_write.c @@ -0,0 +1,205 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Data Pump Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_dpump.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_dpump_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the dpump interface. The call is blocking */ +/* and only returns when there is either an error or when the transfer */ +/* is complete. */ +/* */ +/* INPUT */ +/* */ +/* dpump Pointer to dpump class */ +/* data_pointer Pointer to data to write */ +/* requested_length Length of data to write */ +/* actual_length Actual length of data written */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify the class instance */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_DPUMP_WRITE, dpump, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if(_ux_host_stack_class_instance_verify((UCHAR *) _ux_system_host_class_dpump_name, (VOID *) dpump) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, dpump, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&dpump -> ux_host_class_dpump_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* Start by resetting the actual length of the transfer. */ + *actual_length = 0; + + /* Get the pointer to the bulk out endpoint transfer request. */ + transfer_request = &dpump -> ux_host_class_dpump_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Perform a transfer on the bulk out endpoint until either the transfer is + completed or when there is an error. */ + while (requested_length) + { + + /* Program the maximum authorized length for this transfer_request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_DPUMP_CLASS_TRANSFER_TIMEOUT); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer_request in case some data actually went out. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be sent. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually sent and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + + /* Return success. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to send out. */ + requested_length -= transfer_request_length; + } + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&dpump -> ux_host_class_dpump_semaphore); + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_bandwidth_check.c b/common/core/src/ux_host_stack_bandwidth_check.c new file mode 100644 index 0000000..aa2e6c9 --- /dev/null +++ b/common/core/src/ux_host_stack_bandwidth_check.c @@ -0,0 +1,270 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_bandwidth_check PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will check if there is enough bandwidth on the USB */ +/* for the specified endpoint. The bandwidth requirement is calculated */ +/* by the MaxPacketSize field of endpoint and the speed of the */ +/* endpoint. If the device is on a 1.1 bus or it is a 1.1 device */ +/* behind a 2.0 hub on a 2.0 bus, the device bandwidth must be */ +/* multiplied by 8 on the 1.1 segment. */ +/* */ +/* This algorithm takes into account both TT bandwidth and HCD */ +/* bandwidth. The TTs are attached to the device structure and not */ +/* the hub structure in order to make the stack agnostic of the hub */ +/* class. */ +/* */ +/* INPUT */ +/* */ +/* HCD Pointer to HCD */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_bandwidth_check(UX_HCD *hcd, UX_ENDPOINT *endpoint) +{ + +UX_DEVICE *device; +UX_DEVICE *parent_device; +USHORT hcd_bandwidth_claimed; +USHORT max_packet_size; +LONG packet_size; +USHORT tt_bandwidth_claimed = 0; +ULONG port_index; +ULONG port_map; +ULONG tt_index; +const UCHAR overheads[4][3] = { +/* LS FS HS */ + {63, 45, 173}, /* Control */ + { 0, 9, 38}, /* Isochronous */ + { 0, 13, 55}, /* Bulk */ + {19, 13, 55} /* Interrupt */ +}; + + /* Get the pointer to the device. */ + device = endpoint -> ux_endpoint_device; + + /* Calculate the bandwidth. From USB spec. + * + * The frame unit consumed per byte is like follow: + * Bytes/FrameUnit FrameUnit/byte FrameUnit/byte + * (Overhead included) (HS baseline) (FS baseline) + * Low Speed 187.5 40 8 + * Full Speed 1500 5 1 + * High Speed 7500 1 1/5 + * + * The overhead is like follow: + * Control Isochronous Bulk Interrupt + * bmAttribute (0) (1) (2) (3) + * Low Speed 63 -- -- 19 + * Full Speed 45 9 13 13 + * High Speed 173 38 55 55 + * + * Worst case bit stuffing is calculated as 1.1667 (7/6) times the raw time. + */ + + /* Get maximum packet size. */ + max_packet_size = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_PACKET_SIZE_MASK; + + /* Rough time for possible Bit Stuffing. */ + packet_size = (max_packet_size * 7 + 5) / 6; + + /* Add overhead. */ + packet_size += overheads[endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE][device -> ux_device_speed]; + max_packet_size = (USHORT)packet_size; + + /* Check for high-speed endpoint. */ + if (device -> ux_device_speed == UX_HIGH_SPEED_DEVICE) + { + + /* Get number of transactions. */ + max_packet_size = (USHORT)(max_packet_size * + (((endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK) >> + UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT) + 1)); + } + + /* Calculate the bandwidth claimed by this endpoint for the main bus. */ + if (hcd -> ux_hcd_version != 0x200) + { + + if (device -> ux_device_speed == UX_LOW_SPEED_DEVICE) + /* Low speed transfer takes 40x more units than high speed. */ + hcd_bandwidth_claimed = (USHORT)(max_packet_size * 8 * 5); + else + { + + if (device -> ux_device_speed == UX_FULL_SPEED_DEVICE) + /* Full speed transfer takes 5x more units than high speed. */ + hcd_bandwidth_claimed = (USHORT)(max_packet_size * 5); + else + /* Use high speed timing as base for bus bandwidth calculation. */ + hcd_bandwidth_claimed = (USHORT)max_packet_size; + } + } + else + { + + hcd_bandwidth_claimed = (USHORT)max_packet_size; + if (device -> ux_device_speed == UX_LOW_SPEED_DEVICE) + /* Low speed transfer takes 8x more units than full speed. */ + tt_bandwidth_claimed = (USHORT)(max_packet_size * 8); + else + /* Use full speed timing as base for TT bandwidth calculation. */ + tt_bandwidth_claimed = (USHORT)max_packet_size; + } + + /* Do we have enough on the bus for this new endpoint? */ + if (hcd -> ux_hcd_available_bandwidth < hcd_bandwidth_claimed) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_NO_BANDWIDTH_AVAILABLE, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_NO_BANDWIDTH_AVAILABLE); + + return(UX_NO_BANDWIDTH_AVAILABLE); + } + + /* We need to take care of the case where the endpoint belongs to a USB 1.1 + device that sits behind a 2.0 hub. We ignore cases where the device + is either high speed or the bus is 1.1. */ + if ((device -> ux_device_speed == UX_HIGH_SPEED_DEVICE) || (hcd -> ux_hcd_version != 0x200)) + { + + /* The device is high speed, therefore no need for TT. */ + return(UX_SUCCESS); + } + + /* We have a 1.1 device, check if the parent is a 2.0 hub. */ + parent_device = device -> ux_device_parent; + if (parent_device == UX_NULL) + { + + /* We are at the root, this controller must support 1.1 then! */ + return(UX_SUCCESS); + } + + /* We get here when the parent is a hub. The problem occurs when the hub is itself + connected to a chain of hubs. We need to find the first 2.0 hub parent to this + chain to check the TT. We need to remember the port on which the first 1.1 + device is hooked to. */ + port_index = device -> ux_device_port_location - 1; + + /* Scan the chain of hubs upward. */ + while (parent_device != UX_NULL) + { + + /* Determine if the device is high speed. */ + if (parent_device -> ux_device_speed == UX_HIGH_SPEED_DEVICE) + { + + /* The device is a high speed hub, find the TT that manages the port. + The first 1.1 device is connected to. First we calculate the port + mapping bit. */ + port_map = (ULONG)(1 << port_index); + + /* Parse all the TTs attached to the hub. */ + for (tt_index = 0; tt_index < UX_MAX_TT; tt_index++) + { + + /* Check if this TT owns the port where the device is attached. */ + if ((parent_device -> ux_device_hub_tt[tt_index].ux_hub_tt_port_mapping & port_map) != 0) + { + + /* We have found the port, check if the tt can give us the bandwidth + we want to claim. */ + if (parent_device -> ux_device_hub_tt[tt_index].ux_hub_tt_max_bandwidth < tt_bandwidth_claimed) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_NO_BANDWIDTH_AVAILABLE, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_NO_BANDWIDTH_AVAILABLE); + + return(UX_NO_BANDWIDTH_AVAILABLE); + } + + else + return(UX_SUCCESS); + } + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_NO_BANDWIDTH_AVAILABLE, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_NO_BANDWIDTH_AVAILABLE); + + /* We should never get here !!!!! */ + return(UX_NO_BANDWIDTH_AVAILABLE); + } + + /* We now remember where this hub is located on the parent. */ + port_index = parent_device -> ux_device_port_location - 1; + + /* We go up one level in the hub chain. */ + parent_device = parent_device -> ux_device_parent; + } + + /* We get here when we have not found a 2.0 hub in the list and we got to the root port. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_bandwidth_claim.c b/common/core/src/ux_host_stack_bandwidth_claim.c new file mode 100644 index 0000000..1227bc4 --- /dev/null +++ b/common/core/src/ux_host_stack_bandwidth_claim.c @@ -0,0 +1,244 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_bandwidth_claim PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will reserve bandwidth for a periodic endpoint. The */ +/* bandwidth requirement is calculated by the MaxPacketSize field of */ +/* endpoint and the speed of the endpoint. If the device is on a 1.1 */ +/* bus or it is a 1.1 device behind a 2.0 hub on a 2.0 bus, the device */ +/* bandwidth must be multiplied by 8 on the 1.1 segment. */ +/* */ +/* This algorithm takes into account both TT bandwidth and HCD */ +/* bandwidth. The TTs are attached to the device structure and not */ +/* the hub structure in order to make the stack agnostic of the hub */ +/* class. */ +/* */ +/* INPUT */ +/* */ +/* HCD Pointer to HCD */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_stack_bandwidth_claim(UX_HCD *hcd, UX_ENDPOINT *endpoint) +{ + +UX_DEVICE *device; +UX_DEVICE *parent_device; +USHORT hcd_bandwidth_claimed; +USHORT max_packet_size; +LONG packet_size; +USHORT tt_bandwidth_claimed = 0; +ULONG port_index; +ULONG port_map; +ULONG tt_index; +const UCHAR overheads[4][3] = { +/* LS FS HS */ + {63, 45, 173}, /* Control */ + { 0, 9, 38}, /* Isochronous */ + { 0, 13, 55}, /* Bulk */ + {19, 13, 55} /* Interrupt */ +}; + + /* Get the pointer to the device. */ + device = endpoint -> ux_endpoint_device; + + /* Calculate the bandwidth. From USB spec. + * + * The frame unit consumed per byte is like follow: + * Bytes/FrameUnit FrameUnit/byte FrameUnit/byte + * (Overhead included) (HS baseline) (FS baseline) + * Low Speed 187.5 40 8 + * Full Speed 1500 5 1 + * High Speed 7500 1 1/5 + * + * The overhead is like follow: + * Control Isochronous Bulk Interrupt + * bmAttribute (0) (1) (2) (3) + * Low Speed 63 -- -- 19 + * Full Speed 45 9 13 13 + * High Speed 173 38 55 55 + * + * Worst case bit stuffing is calculated as 1.1667 (7/6) times the raw time. + */ + + /* Get maximum packet size. */ + max_packet_size = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_PACKET_SIZE_MASK; + + /* Rough time for possible Bit Stuffing. */ + packet_size = (max_packet_size * 7 + 5) / 6; + + /* Add overhead. */ + packet_size += overheads[endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE][device -> ux_device_speed]; + max_packet_size = (USHORT)packet_size; + + /* Check for high-speed endpoint. */ + if (device -> ux_device_speed == UX_HIGH_SPEED_DEVICE) + { + + /* Get number of transactions. */ + max_packet_size = (USHORT)(max_packet_size * + (((endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK) >> + UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT) + 1)); + } + + /* Calculate the bandwidth claimed by this endpoint for the main bus. */ + if (hcd -> ux_hcd_version != 0x200) + { + + if (device -> ux_device_speed == UX_LOW_SPEED_DEVICE) + /* Low speed transfer takes 40x more units than high speed. */ + hcd_bandwidth_claimed = (USHORT)(max_packet_size * 8 * 5); + else + { + + if (device -> ux_device_speed == UX_FULL_SPEED_DEVICE) + /* Full speed transfer takes 5x more units than high speed. */ + hcd_bandwidth_claimed = (USHORT)(max_packet_size * 5); + else + /* Use high speed timing as base for bus bandwidth calculation. */ + hcd_bandwidth_claimed = (USHORT)max_packet_size; + } + } + else + { + + hcd_bandwidth_claimed = (USHORT)max_packet_size; + if (device -> ux_device_speed == UX_LOW_SPEED_DEVICE) + /* Low speed transfer takes 8x more units than full speed. */ + tt_bandwidth_claimed = (USHORT)(max_packet_size * 8); + else + /* Use full speed timing as base for TT bandwidth calculation. */ + tt_bandwidth_claimed = (USHORT)max_packet_size; + } + + /* Allocate the HCD bandwidth, since it's already checked by _bandwidth_check. */ + hcd -> ux_hcd_available_bandwidth -= hcd_bandwidth_claimed; + + /* We need to take care of the case where the endpoint belongs to a USB 1.1 + device that sits behind a 2.0 hub. We ignore cases where the device + is either high speed or the bus is 1.1. */ + if ((device -> ux_device_speed == UX_HIGH_SPEED_DEVICE) || (hcd -> ux_hcd_version != 0x200)) + { + + /* The device is high speed, therefore no need for TT. */ + return; + } + + /* We have a 1.1 device, check if the parent is a 2.0 hub. */ + parent_device = device -> ux_device_parent; + if (parent_device == UX_NULL) + { + + /* We are at the root, must be a 1.1 controller then! */ + return; + } + + /* We get here when the parent is a hub. The problem occurs when the hub is + itself connected to a chain of hubs. We need to find the first 2.0 hub + parent to this chain to check the TT. We need to remember the port on + which the first 1.1 device is hooked to. */ + port_index = device -> ux_device_port_location - 1; + + /* Scan the chain of hubs upward. */ + while (parent_device != UX_NULL) + { + + /* Is the device high speed? */ + if (parent_device -> ux_device_speed == UX_HIGH_SPEED_DEVICE) + { + + /* The device is a high speed hub, find the TT that manages the port. + The first 1.1 device is connected to. First we calculate the port + mapping bit. */ + port_map = (ULONG)(1 << port_index); + + /* Parse all the TTs attached to the hub. + Since we confirmed exist of TT in previous _check, + just do while loop here. + */ + tt_index = 0; + while(1) + { + /* Check if this TT owns the port where the device is attached. */ + if ((parent_device -> ux_device_hub_tt[tt_index].ux_hub_tt_port_mapping & port_map) != 0) + { + + /* We have found the port, check if the tt can give us the bandwidth + we want to claim. */ + parent_device -> ux_device_hub_tt[tt_index].ux_hub_tt_max_bandwidth -= tt_bandwidth_claimed; + return; + } + + /* Try next index. */ + tt_index ++; + } + } + + /* We now remember where this hub is located on the parent. */ + port_index = parent_device -> ux_device_port_location - 1; + + /* We go up one level in the hub chain. */ + parent_device = parent_device -> ux_device_parent; + } + + /* We get here when we have not found a 2.0 hub in the list and we got + to the root port. */ + return; +} diff --git a/common/core/src/ux_host_stack_bandwidth_release.c b/common/core/src/ux_host_stack_bandwidth_release.c new file mode 100644 index 0000000..082af6f --- /dev/null +++ b/common/core/src/ux_host_stack_bandwidth_release.c @@ -0,0 +1,240 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_bandwidth_release PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will release bandwidth for a periodic endpoint. The */ +/* bandwidth requirement is calculated by the MaxPacketSize field of */ +/* endpoint and the speed of the endpoint. If the device is on a 1.1 */ +/* bus or it is a 1.1 device behind a 2.0 hub on a 2.0 bus, the device */ +/* bandwidth must be multiplied by 8 on the 1.1 segment. */ +/* */ +/* This algorithm takes into account both TT bandwidth and HCD */ +/* bandwidth. The TTs are attached to the device structure and not the */ +/* hub structure in order to make the stack agnostic of the hub class. */ +/* */ +/* INPUT */ +/* */ +/* HCD Pointer to HCD */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_stack_bandwidth_release(UX_HCD *hcd, UX_ENDPOINT *endpoint) +{ + +UX_DEVICE *device; +UX_DEVICE *parent_device; +USHORT hcd_bandwidth_claimed; +USHORT max_packet_size; +LONG packet_size; +USHORT tt_bandwidth_claimed = 0; +ULONG port_index; +ULONG port_map; +ULONG tt_index; +const UCHAR overheads[4][3] = { +/* LS FS HS */ + {63, 45, 173}, /* Control */ + { 0, 9, 38}, /* Isochronous */ + { 0, 13, 55}, /* Bulk */ + {19, 13, 55} /* Interrupt */ +}; + + /* Get the pointer to the device. */ + device = endpoint -> ux_endpoint_device; + + /* Calculate the bandwidth. From USB spec. + * + * The frame unit consumed per byte is like follow: + * Bytes/FrameUnit FrameUnit/byte FrameUnit/byte + * (Overhead included) (HS baseline) (FS baseline) + * Low Speed 187.5 40 8 + * Full Speed 1500 5 1 + * High Speed 7500 1 1/5 + * + * The overhead is like follow: + * Control Isochronous Bulk Interrupt + * bmAttribute (0) (1) (2) (3) + * Low Speed 63 -- -- 19 + * Full Speed 45 9 13 13 + * High Speed 173 38 55 55 + * + * Worst case bit stuffing is calculated as 1.1667 (7/6) times the raw time. + */ + + /* Get maximum packet size. */ + max_packet_size = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_PACKET_SIZE_MASK; + + /* Rough time for possible Bit Stuffing. */ + packet_size = (max_packet_size * 7 + 5) / 6; + + /* Add overhead. */ + packet_size += overheads[endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE][device -> ux_device_speed]; + max_packet_size = (USHORT)packet_size; + + /* Check for high-speed endpoint. */ + if (device -> ux_device_speed == UX_HIGH_SPEED_DEVICE) + { + + /* Get number of transactions. */ + max_packet_size = (USHORT)(max_packet_size * + (((endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK) >> + UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT) + 1)); + } + + /* Calculate the bandwidth claimed by this endpoint for the main bus. */ + if (hcd -> ux_hcd_version != 0x200) + { + + if (device -> ux_device_speed == UX_LOW_SPEED_DEVICE) + /* Low speed transfer takes 40x more units than high speed. */ + hcd_bandwidth_claimed = (USHORT)(max_packet_size * 8 * 5); + else + { + + if (device -> ux_device_speed == UX_FULL_SPEED_DEVICE) + /* Full speed transfer takes 5x more units than high speed. */ + hcd_bandwidth_claimed = (USHORT)(max_packet_size * 5); + else + /* Use high speed timing as base for bus bandwidth calculation. */ + hcd_bandwidth_claimed = (USHORT)max_packet_size; + } + } + else + { + + hcd_bandwidth_claimed = (USHORT)max_packet_size; + if (device -> ux_device_speed == UX_LOW_SPEED_DEVICE) + /* Low speed transfer takes 8x more units than full speed. */ + tt_bandwidth_claimed = (USHORT)(max_packet_size * 8); + else + /* Use full speed timing as base for TT bandwidth calculation. */ + tt_bandwidth_claimed = (USHORT)max_packet_size; + } + + /* Free the HCD bandwidth. */ + hcd -> ux_hcd_available_bandwidth += hcd_bandwidth_claimed; + + /* We need to take care of the case where the endpoint belongs to a USB 1.1 + device that sits behind a 2.0 hub. We ignore cases where the device + is either high speed or the bus is 1.1. */ + if ((device -> ux_device_speed == UX_HIGH_SPEED_DEVICE) || (hcd -> ux_hcd_version != 0x200)) + { + + /* The device is high speed, therefore no need for TT. */ + return; + } + + /* We have a 1.1 device, check if the parent is a 2.0 hub. */ + parent_device = device -> ux_device_parent; + if (parent_device == UX_NULL) + { + + /* We are at the root, must be a 1.1 controller then! */ + return; + } + + /* We get here when the parent is a hub. The problem occurs when the hub is itself + connected to a chain of hubs. We need to find the first 2.0 hub parent to this chain + to check the TT. We need to remember the port on which the first 1.1 device is + hooked to. */ + port_index = device -> ux_device_port_location - 1; + + /* Scan the chain of hubs upward. */ + while (parent_device != UX_NULL) + { + + /* Check for a high speed device. */ + if (parent_device -> ux_device_speed == UX_HIGH_SPEED_DEVICE) + { + + /* The device is a high speed hub, find the TT that manages the port. + The first 1.1 device is connected to. First we calculate the port mapping bit. */ + port_map = (ULONG)(1 << port_index); + + /* Parse all the TTs attached to the hub. */ + for (tt_index = 0; tt_index < UX_MAX_TT; tt_index++) + { + + /* Check if this TT owns the port where the device is attached. */ + if ((parent_device -> ux_device_hub_tt[tt_index].ux_hub_tt_port_mapping & port_map) != 0) + { + + /* We have found the port, check if the tt can give us the bandwidth + we want to claim. */ + parent_device -> ux_device_hub_tt[tt_index].ux_hub_tt_max_bandwidth += tt_bandwidth_claimed; + return; + } + } + + /* We should never get here!!!!! */ + return; + } + + /* We now remember where this hub is located on the parent. */ + port_index = parent_device -> ux_device_port_location - 1; + + /* We go up one level in the hub chain. */ + parent_device = parent_device -> ux_device_parent; + } + + /* We get here when we have not found a 2.0 hub in the list and we got + to the root port. */ + return; +} + diff --git a/common/core/src/ux_host_stack_class_call.c b/common/core/src/ux_host_stack_class_call.c new file mode 100644 index 0000000..f3a8513 --- /dev/null +++ b/common/core/src/ux_host_stack_class_call.c @@ -0,0 +1,109 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_class_call PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will call all the registered classes to the USBX */ +/* stack. Each class will have the possibility to own the device or */ +/* one of the interfaces of a device. */ +/* */ +/* INPUT */ +/* */ +/* class_command Class command structure */ +/* */ +/* OUTPUT */ +/* */ +/* Number of owners */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_entry_function) Class entry function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_HOST_CLASS *_ux_host_stack_class_call(UX_HOST_CLASS_COMMAND *class_command) +{ + +UX_HOST_CLASS *class; +ULONG class_index; +UINT status; + + + /* Start from the 1st registered classes with USBX. */ + class = _ux_system_host -> ux_system_host_class_array; + + /* Parse all the class drivers. */ + for (class_index = 0; class_index < _ux_system_host -> ux_system_host_max_class; class_index++) + { + + /* Check if this class driver is used. */ + if (class -> ux_host_class_status == UX_USED) + { + + /* We have found a potential candidate. Call this registered class entry function. */ + status = class -> ux_host_class_entry_function(class_command); + + /* The status tells us if the registered class wants to own this class. */ + if (status == UX_SUCCESS) + { + + /* Yes, return this class pointer. */ + return(class); + } + } + + /* Move to the next registered class. */ + class++; + } + + /* There is no driver who want to own this class! */ + return(UX_NULL); +} + diff --git a/common/core/src/ux_host_stack_class_device_scan.c b/common/core/src/ux_host_stack_class_device_scan.c new file mode 100644 index 0000000..e3ffaa4 --- /dev/null +++ b/common/core/src/ux_host_stack_class_device_scan.c @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_class_device_scan PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will scan all registered classes with a device */ +/* candidate. Priority is given to the PID/VID and then the */ +/* Class/Subclass/Protocol. */ +/* */ +/* INPUT */ +/* */ +/* device Pointer to device */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_call Call host stack class */ +/* (ux_host_class_entry_function) Class entry function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_class_device_scan(UX_DEVICE *device) +{ + +UINT status; +UX_HOST_CLASS *class; +UX_HOST_CLASS_COMMAND class_command; + + /* Perform the command initialization. */ + class_command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_QUERY; + class_command.ux_host_class_command_container = (VOID *) device; + class_command.ux_host_class_command_vid = device -> ux_device_descriptor.idVendor; + class_command.ux_host_class_command_pid = device -> ux_device_descriptor.idProduct; + class_command.ux_host_class_command_class = device -> ux_device_descriptor.bDeviceClass; + class_command.ux_host_class_command_subclass = device -> ux_device_descriptor.bDeviceSubClass; + class_command.ux_host_class_command_subclass = device -> ux_device_descriptor.bDeviceSubClass; + class_command.ux_host_class_command_protocol = device -> ux_device_descriptor.bDeviceProtocol; + class_command.ux_host_class_command_iad_class = 0; + class_command.ux_host_class_command_iad_subclass = 0; + class_command.ux_host_class_command_iad_protocol = 0; + + /* We start with the PID/VID for this device. */ + class_command.ux_host_class_command_usage = UX_HOST_CLASS_COMMAND_USAGE_PIDVID; + class = _ux_host_stack_class_call(&class_command); + + /* On return, either we have found a class or the device is still an orphan. */ + if (class != UX_NULL) + { + + device -> ux_device_class = class; + class_command.ux_host_class_command_class_ptr = class; + class_command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE; + status = device -> ux_device_class -> ux_host_class_entry_function(&class_command); + + /* Return result of activation. */ + return(status); + } + + /* It the PID/VID did not work, we continue looking for the Class\Subclass\Protocol match. */ + class_command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_QUERY; + class_command.ux_host_class_command_container = (VOID *) device; + class_command.ux_host_class_command_usage = UX_HOST_CLASS_COMMAND_USAGE_CSP; + + class = _ux_host_stack_class_call(&class_command); + + /* On return, either we have found a class or the device is still an orphan. */ + if (class != UX_NULL) + { + + device -> ux_device_class = class; + class_command.ux_host_class_command_class_ptr = class; + class_command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE; + status = device -> ux_device_class -> ux_host_class_entry_function(&class_command); + + /* Return result of activation. */ + return(status); + } + + /* Return an error. */ + return(UX_NO_CLASS_MATCH); +} + diff --git a/common/core/src/ux_host_stack_class_get.c b/common/core/src/ux_host_stack_class_get.c new file mode 100644 index 0000000..121d48b --- /dev/null +++ b/common/core/src/ux_host_stack_class_get.c @@ -0,0 +1,124 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_class_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns a pointer to the class container. A class */ +/* needs to obtain its container from the USBX stack to search for */ +/* instances when a driver or an application wants to open a device. */ +/* */ +/* Note: The C string of class_name must be NULL-terminated and the */ +/* length of it (without the NULL-terminator itself) must be no larger */ +/* than UX_MAX_CLASS_NAME_LENGTH. */ +/* */ +/* INPUT */ +/* */ +/* class_name Name of class */ +/* class Class pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_string_length_check Check C string and return its */ +/* length if null-terminated */ +/* _ux_utility_memory_compare Compare memory blocks */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_class_get(UCHAR *class_name, UX_HOST_CLASS **host_class) +{ + +UX_HOST_CLASS *class_ptr; +ULONG class_index; +UINT status; +UINT class_name_length = 0; + + + /* Get the length of the class name (exclude null-terminator). */ + status = _ux_utility_string_length_check(class_name, &class_name_length, UX_MAX_CLASS_NAME_LENGTH); + if (status) + return(status); + + /* We need to parse the class driver table. */ + class_ptr = _ux_system_host -> ux_system_host_class_array; + for (class_index = 0; class_index < _ux_system_host -> ux_system_host_max_class; class_index++) + { + + /* Check if this class is already being used. */ + if (class_ptr -> ux_host_class_status == UX_USED) + { + + /* We have found a container. Check if this is the one we need (compare including null-terminator). */ + if (_ux_utility_memory_compare(class_ptr -> ux_host_class_name, class_name, class_name_length + 1) == UX_SUCCESS) + { + + /* The class container was found. Update the pointer to the class container for the caller. */ + *host_class = class_ptr; + + /* Return success. */ + return(UX_SUCCESS); + } + } + + /* Move to the next class. */ + class_ptr++; + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_UNKNOWN, class_name, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* This class does not exist, return an error. */ + return(UX_HOST_CLASS_UNKNOWN); +} + diff --git a/common/core/src/ux_host_stack_class_instance_create.c b/common/core/src/ux_host_stack_class_instance_create.c new file mode 100644 index 0000000..2784ca0 --- /dev/null +++ b/common/core/src/ux_host_stack_class_instance_create.c @@ -0,0 +1,114 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_class_instance_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a new class instance for a class container. */ +/* The instance of a class is not contained in the class code to */ +/* reduce the class driver complexity. Rather, each class instance is */ +/* attached to class container. */ +/* */ +/* INPUT */ +/* */ +/* class Pointer to class */ +/* class_instance Pointer to class instance */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_class_instance_create(UX_HOST_CLASS *host_class, VOID *class_instance) +{ + +VOID **current_class_instance; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_CLASS_INSTANCE_CREATE, host_class, class_instance, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_CLASS_INSTANCE, class_instance, 0, 0, 0) + + /* Start with the first class instance attached to the class container. */ + current_class_instance = host_class -> ux_host_class_first_instance; + + /* Check if there are any instances attached. */ + if (current_class_instance == UX_NULL) + { + + /* Since it is the first class, attach it to the class container. */ + host_class -> ux_host_class_first_instance = class_instance; + + /* Return successful completion. */ + return(UX_SUCCESS); + } + + /* Traverse the list of the class instances until we find the last class. */ + while (*current_class_instance != UX_NULL) + { + + /* Point to the next class instance. */ + current_class_instance = *current_class_instance; + } + + /* We have reached the last class, hook the new class to the end. This way, we preserve + the chronological order of the class instances. */ + *current_class_instance = class_instance; + + /* Return successful completion to caller. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_class_instance_destroy.c b/common/core/src/ux_host_stack_class_instance_destroy.c new file mode 100644 index 0000000..0ab3709 --- /dev/null +++ b/common/core/src/ux_host_stack_class_instance_destroy.c @@ -0,0 +1,143 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_class_instance_destroy PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function destroys a class instance for a class container. */ +/* */ +/* INPUT */ +/* */ +/* class Pointer to class */ +/* class_instance Pointer to class instance */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_class_instance_destroy(UX_HOST_CLASS *host_class, VOID *class_instance) +{ + +VOID **current_class_instance; +VOID **next_class_instance; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_CLASS_INSTANCE_DESTROY, host_class, class_instance, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(class_instance); + + /* Get the pointer to the instance pointed by the instance to destroy. */ + next_class_instance = class_instance; + next_class_instance = *next_class_instance; + + /* Start with the first class instance attached to the class container. */ + current_class_instance = host_class -> ux_host_class_first_instance; + + /* Check if there are any instances attached. */ + if (current_class_instance == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, class_instance, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* The first instance is a special case because it is attached to the class + container. */ + if (current_class_instance == class_instance) + { + + /* Point to next class instance. */ + host_class -> ux_host_class_first_instance = next_class_instance; + + /* Return success. */ + return(UX_SUCCESS); + } + + /* Traverse the list of the class instances until we found the right one. */ + while (*current_class_instance != UX_NULL) + { + + /* Check to see if this class is the one we need to destroy. */ + if(*current_class_instance == class_instance) + { + + /* Point to next class instance. */ + *current_class_instance = next_class_instance; + + /* Return success. */ + return(UX_SUCCESS); + } + + /* Points to the next class instance. */ + current_class_instance = *current_class_instance; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, class_instance, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error to caller. */ + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); +} + diff --git a/common/core/src/ux_host_stack_class_instance_get.c b/common/core/src/ux_host_stack_class_instance_get.c new file mode 100644 index 0000000..8259858 --- /dev/null +++ b/common/core/src/ux_host_stack_class_instance_get.c @@ -0,0 +1,113 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_class_instance_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns a class instance pointer for a specific */ +/* class. The instance of a class is not contained in the class code */ +/* to reduce the class complexity. Rather, each class instance is */ +/* attached to class container. */ +/* */ +/* INPUT */ +/* */ +/* class Pointer to class */ +/* class_index Index of class */ +/* class_instance Destination of class instance */ +/* pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_class_instance_get(UX_HOST_CLASS *host_class, UINT class_index, VOID **class_instance) +{ + +VOID **current_class_instance; + + + /* Start with the first class instance attached to the class container. */ + current_class_instance = host_class -> ux_host_class_first_instance; + + /* Check if there are any instances attached. */ + if(current_class_instance == UX_NULL) + { + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Traverse the list of the class instances until we found the right one. */ + while (class_index-- != 0) + { + + /* Points to the next class instance. */ + current_class_instance = *current_class_instance; + + /* Check if we have reached the end of the list of the class instances. */ + if (current_class_instance == UX_NULL) + { + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + } + + /* Update the class instance pointer from the caller. */ + *class_instance = current_class_instance; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_class_instance_verify.c b/common/core/src/ux_host_stack_class_instance_verify.c new file mode 100644 index 0000000..41aa28c --- /dev/null +++ b/common/core/src/ux_host_stack_class_instance_verify.c @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_class_instance_verify PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function ensures that a given instance exists. An application */ +/* is not responsible for keeping the instance valid pointer. The */ +/* class is responsible for the instance checks if the instance is */ +/* still valid. */ +/* */ +/* INPUT */ +/* */ +/* class_name Name of class */ +/* class_instance Pointer to class instance */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_string_length_check Check C string and return its */ +/* length if null-terminated */ +/* _ux_utility_memory_compare Compare blocks of memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_class_instance_verify(UCHAR *class_name, VOID *class_instance) +{ + +UX_HOST_CLASS *class; +ULONG class_index; +VOID **current_class_instance; +UINT status; +UINT class_name_length = 0; + + + /* Get the length of the class name (exclude null-terminator). */ + status = _ux_utility_string_length_check(class_name, &class_name_length, UX_MAX_CLASS_NAME_LENGTH); + if (status) + return(status); + + /* We need to parse the class table. */ + class = _ux_system_host -> ux_system_host_class_array; + for(class_index = 0; class_index < _ux_system_host -> ux_system_host_max_class; class_index++) + { + + /* Check if this class is already used. */ + if (class -> ux_host_class_status == UX_USED) + { + + /* Start with the first class instance attached to the class container. */ + current_class_instance = class -> ux_host_class_first_instance; + + /* Traverse the list of the class instances until we find the correct instance. */ + while (current_class_instance != UX_NULL) + { + + /* Check the class instance attached to the container with the caller's + instance. */ + if (current_class_instance == class_instance) + { + + /* We have found the class container. Check if this is the one we need (compare including null-terminator). */ + if (_ux_utility_memory_compare(class -> ux_host_class_name, class_name, class_name_length + 1) == UX_SUCCESS) + return(UX_SUCCESS); + } + + /* Points to the next class instance. */ + current_class_instance = *current_class_instance; + } + } + + /* Move to the next class. */ + class++; + } + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, class_instance, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* This class does not exist. */ + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); +} + diff --git a/common/core/src/ux_host_stack_class_interface_scan.c b/common/core/src/ux_host_stack_class_interface_scan.c new file mode 100644 index 0000000..d202d77 --- /dev/null +++ b/common/core/src/ux_host_stack_class_interface_scan.c @@ -0,0 +1,196 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_class_interface_scan PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will scan all default interfaces for a single */ +/* configuration and call the registered class with the */ +/* Class/SubClass/Protocol of the interface. */ +/* */ +/* If the device has multiple configurations (like the Apple iPod), */ +/* the first configuration is treated as the default configuration. */ +/* If a device which has multiple configurations wants to control the */ +/* configuration selection, it must ensure that the PID/VID based */ +/* class at the device level claims the entire device. */ +/* */ +/* */ +/* For the interface, there is no reason to use the PID/VID has a */ +/* binding element as classes that trigger on PID/VID will be called */ +/* by the device descriptor scanning process. */ +/* */ +/* INPUT */ +/* */ +/* device Device pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Result of operation */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_call Call class command */ +/* _ux_host_stack_device_configuration_select */ +/* Select configuration */ +/* (ux_host_stack_class_call) Call class from host stack */ +/* (ux_host_class_entry_function) Class entry function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_class_interface_scan(UX_DEVICE *device) +{ + +UX_CONFIGURATION *configuration; +UX_INTERFACE *interface; +UINT nb_class_owners; +UX_HOST_CLASS *class; +UX_HOST_CLASS_COMMAND class_command; +UINT status; + + /* Initialize class owners to 0. */ + nb_class_owners = 0; + + /* Get the 1st and only configuration. If the device has multiple + configurations, we simply use the first one as default. */ + configuration = device -> ux_device_first_configuration; + if (configuration == UX_NULL) + return(UX_ERROR); + + /* Get the first interface container for this configuration. */ + interface = configuration -> ux_configuration_first_interface; + + /* We now scan all the alternate settings 0 for each of the interfaces. */ + while (interface != UX_NULL) + { + + /* Is there a default interface? */ + if(interface -> ux_interface_descriptor.bAlternateSetting == 0) + { + + /* We have a default interface for this configuration. Call each class + with the class\subclass\protocol. We include the IAD for the cdc classes. */ + class_command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_QUERY; + class_command.ux_host_class_command_container = (VOID *)interface; + class_command.ux_host_class_command_usage = UX_HOST_CLASS_COMMAND_USAGE_CSP; + class_command.ux_host_class_command_class = interface -> ux_interface_descriptor.bInterfaceClass; + class_command.ux_host_class_command_subclass = interface -> ux_interface_descriptor.bInterfaceSubClass; + class_command.ux_host_class_command_protocol = interface -> ux_interface_descriptor.bInterfaceProtocol; + class_command.ux_host_class_command_iad_class = interface -> ux_interface_iad_class ; + class_command.ux_host_class_command_iad_subclass = interface -> ux_interface_iad_subclass; + class_command.ux_host_class_command_iad_protocol = interface -> ux_interface_iad_protocol; + + class = _ux_host_stack_class_call(&class_command); + + /* On return, either we have found a class or the interface is still an orphan. */ + if (class != UX_NULL) + { + + /* There is a class. */ + nb_class_owners++; + interface -> ux_interface_class = class; + } + } + + /* point to the next interface until end of the list. */ + interface = interface -> ux_interface_next_interface; + } + + /* Assume no classes. */ + status = UX_NO_CLASS_MATCH; + + /* Check the number of class owner found. */ + if (nb_class_owners != 0) + { + + /* If we have found one or more classes for any of the interfaces, + we can safely do a SET_CONFIGURATION of the device. */ + status = _ux_host_stack_device_configuration_select(configuration); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* The device is in the CONFIGURED state, we have to call each of the classes + again with an ACTIVATE signal. */ + interface = configuration -> ux_configuration_first_interface; + + while (interface != UX_NULL) + { + + /* Is there a default interface? */ + if (interface -> ux_interface_descriptor.bAlternateSetting == 0) + { + + /* We have found the default interface. If this interface is owned, + activate its class. */ + class_command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE; + class_command.ux_host_class_command_container = (VOID *) interface; + + if (interface -> ux_interface_class != UX_NULL) + { + + /* Save the class in the command container */ + class_command.ux_host_class_command_class_ptr = interface -> ux_interface_class; + + /* Send the ACTIVATE command to the class */ + status = interface -> ux_interface_class -> ux_host_class_entry_function(&class_command); + + } + } + + /* Point to the next interface until end of the list. */ + interface = interface -> ux_interface_next_interface; + } + } + } + + /* Return operation result. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_class_register.c b/common/core/src/ux_host_stack_class_register.c new file mode 100644 index 0000000..5628401 --- /dev/null +++ b/common/core/src/ux_host_stack_class_register.c @@ -0,0 +1,153 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_class_register PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers a USB class to the USB stack. The Class */ +/* must specify an entry point for the USB stack to send commands */ +/* such as: */ +/* */ +/* UX_HOST_CLASS_COMMAND_QUERY */ +/* UX_HOST_CLASS_COMMAND_ACTIVATE */ +/* UX_HOST_CLASS_COMMAND_DESTROY */ +/* */ +/* Note: The C string of class_name must be NULL-terminated and the */ +/* length of it (without the NULL-terminator itself) must be no larger */ +/* than UX_MAX_CLASS_NAME_LENGTH. */ +/* */ +/* INPUT */ +/* */ +/* class_name Name of class */ +/* class_entry_function Entry function of the class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_string_length_check Check C string and return */ +/* length if null-terminated */ +/* _ux_utility_memory_copy Copy memory block */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_class_register(UCHAR *class_name, + UINT (*class_entry_function)(struct UX_HOST_CLASS_COMMAND_STRUCT *)) +{ + +UX_HOST_CLASS *class; +ULONG class_index; +UINT status; +UINT class_name_length = 0; + + + /* Get the length of the class name (exclude null-terminator). */ + status = _ux_utility_string_length_check(class_name, &class_name_length, UX_MAX_CLASS_NAME_LENGTH); + if (status) + return(status); + + /* We need to parse the class table to find an empty spot. */ + class = _ux_system_host -> ux_system_host_class_array; + for (class_index = 0; class_index < _ux_system_host -> ux_system_host_max_class; class_index++) + { + + /* Check if this class is already used. */ + if (class -> ux_host_class_status == UX_UNUSED) + { + + /* We have found a free container for the class. Copy the name (with null-terminator). */ + _ux_utility_memory_copy(class -> ux_host_class_name, class_name, class_name_length + 1); + + /* Memorize the entry function of this class. */ + class -> ux_host_class_entry_function = class_entry_function; + + /* Mark it as used. */ + class -> ux_host_class_status = UX_USED; + + /* Return successful completion. */ + return(UX_SUCCESS); + } + + /* Do a sanity check to make sure the class is not already installed by + mistake. To verify this, we simple check for the class entry point. */ + else + { + + /* Check for an already installed class entry function. */ + if(class -> ux_host_class_entry_function == class_entry_function) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_INIT, UX_HOST_CLASS_ALREADY_INSTALLED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_ALREADY_INSTALLED, class_name, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Yes, return an error. */ + return(UX_HOST_CLASS_ALREADY_INSTALLED); + } + } + + /* Move to the next class. */ + class++; + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_ARRAY_FULL, class_name, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_INIT, UX_MEMORY_ARRAY_FULL); + + /* No more entries in the class table. */ + return(UX_MEMORY_ARRAY_FULL); +} + diff --git a/common/core/src/ux_host_stack_configuration_descriptor_parse.c b/common/core/src/ux_host_stack_configuration_descriptor_parse.c new file mode 100644 index 0000000..4677860 --- /dev/null +++ b/common/core/src/ux_host_stack_configuration_descriptor_parse.c @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_configuration_descriptor_parse PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads the entire configuration descriptor and */ +/* enumerates the interfaces, binds the interface to a class driver... */ +/* if the device has multiple configurations, we read all the */ +/* configurations but do not instantiate any configuration. Rather we */ +/* let a class driver do the work. */ +/* */ +/* INPUT */ +/* */ +/* device Pointer to device */ +/* configuration Pointer to configuration */ +/* configuration_index Index of configuration */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interfaces_scan Scan host interfaces */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate block of memory */ +/* _ux_utility_memory_free Free block of memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_configuration_descriptor_parse(UX_DEVICE *device, UX_CONFIGURATION *configuration, + UINT configuration_index) +{ + +UX_TRANSFER *transfer_request; +UINT status; +UCHAR *descriptor; +UX_ENDPOINT *control_endpoint; +ULONG total_configuration_length; + + + /* Retrieve the pointer to the control endpoint and its transfer_request. */ + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Retrieve the size of all the configuration descriptor. */ + total_configuration_length = configuration -> ux_configuration_descriptor.wTotalLength; + + /* Allocate enough memory to read all descriptors attached to this configuration. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, total_configuration_length); + + /* Determine if the memory was allocated. */ + if (descriptor == UX_NULL) + { + + /* No, return an error. */ + return(UX_MEMORY_INSUFFICIENT); + } + else + { + + /* Create a transfer_request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = total_configuration_length; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = configuration_index | (UINT)(UX_CONFIGURATION_DESCRIPTOR_ITEM << 8); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == total_configuration_length)) + { + + /* The entire descriptor now contains the configuration descriptor, + the interface(s) descriptors, all alternate settings, endpoints + and descriptor specific to the class. The descriptor is parsed for all interfaces. */ + status = _ux_host_stack_interfaces_scan(configuration, descriptor); + } + } + + /* Free all used resources. */ + _ux_utility_memory_free(descriptor); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_configuration_enumerate.c b/common/core/src/ux_host_stack_configuration_enumerate.c new file mode 100644 index 0000000..5b7158d --- /dev/null +++ b/common/core/src/ux_host_stack_configuration_enumerate.c @@ -0,0 +1,189 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_configuration_enumerate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads the configuration descriptor, creates the */ +/* configuration container(s) for the device, and enumerates all found */ +/* configurations. */ +/* */ +/* At this stage, only the containers for each subcomponents are */ +/* linked. No configuration, interface or endpoints are active unless */ +/* a class issues a SET_CONFIGURATION. */ +/* */ +/* INPUT */ +/* */ +/* device Pointer to device */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_descriptor_parse */ +/* Parse configuration descriptor*/ +/* _ux_host_stack_configuration_instance_delete */ +/* Delete configuration instance */ +/* _ux_host_stack_new_configuration_create */ +/* Create new configuration */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_utility_memory_allocate Allocate block of memory */ +/* _ux_utility_memory_free Free block of memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_configuration_enumerate(UX_DEVICE *device) +{ + +UX_TRANSFER *transfer_request; +UINT status = UX_ERROR; +UCHAR * descriptor; +UX_ENDPOINT *control_endpoint; +UX_CONFIGURATION *configuration; +ULONG nb_configurations; +ULONG configuration_index; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_CONFIGURATION_ENUMERATE, device, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Retrieve the pointer to the control endpoint and its transfer_request. */ + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the configuration descriptor the first time we read + only the configuration descriptor when we have the configuration descriptor, we have + the length of the entire configuration\interface\endpoint descriptors. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_CONFIGURATION_DESCRIPTOR_LENGTH); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* There maybe multiple configurations for this device. */ + nb_configurations = device -> ux_device_descriptor.bNumConfigurations; + + /* Parse all the configurations attached to the device. We start with the first index. + The index and the actual configuration value may be different according to the USB specification! */ + for (configuration_index = 0; configuration_index < nb_configurations; configuration_index++) + { + + /* Create a transfer_request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = UX_CONFIGURATION_DESCRIPTOR_LENGTH; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = configuration_index | (UINT)(UX_CONFIGURATION_DESCRIPTOR_ITEM << 8); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == UX_CONFIGURATION_DESCRIPTOR_LENGTH)) + { + + /* Allocate some memory for the container of this descriptor. */ + configuration = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_CONFIGURATION)); + + /* Check to see if the block was allocated. */ + if (configuration != UX_NULL) + { + + /* This configuration must be linked to the device. */ + _ux_host_stack_new_configuration_create(device, configuration); + + /* The descriptor is in a packed format, parse it locally. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, (UCHAR *) &configuration -> ux_configuration_descriptor); + + /* Parse the device descriptor so that we can retrieve the length + of the entire configuration. */ + status = _ux_host_stack_configuration_descriptor_parse(device, configuration, configuration_index); + + /* Check the completion status. */ + if (status != UX_SUCCESS) + { + /* Error, delete the configuration instance. */ + _ux_host_stack_configuration_instance_delete(configuration); + } + } + else + { + + /* Cannot allocate configuration memory. Abort enumeration */ + status = UX_MEMORY_INSUFFICIENT; + + break; + } + } + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* The device descriptor does not contain the right amount of data. Maybe corruption. */ + status = UX_DESCRIPTOR_CORRUPTED; + + break; + } + + } + + /* Free all used resources. */ + _ux_utility_memory_free(descriptor); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_configuration_instance_create.c b/common/core/src/ux_host_stack_configuration_instance_create.c new file mode 100644 index 0000000..4c2aaa7 --- /dev/null +++ b/common/core/src/ux_host_stack_configuration_instance_create.c @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_configuration_instance_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will create a configuration instance. It scan all the */ +/* interfaces hooked to the configuration and enable each interface */ +/* with the alternate setting 0. */ +/* */ +/* INPUT */ +/* */ +/* configuration Pointer to configuration */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_instance_create Create interface instance */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_configuration_instance_create(UX_CONFIGURATION *configuration) +{ + +UX_INTERFACE *interface; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_CONFIGURATION_INSTANCE_CREATE, configuration, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Obtain the first interface for this configuration. */ + interface = configuration -> ux_configuration_first_interface; + + /* Each selected alternate setting 0 for each interface must be created. */ + while (interface != UX_NULL) + { + + /* Check if we are dealing with the first alternate setting. */ + if (interface -> ux_interface_descriptor.bAlternateSetting == 0) + { + /* Create the interface. */ + status = _ux_host_stack_interface_instance_create(interface); + + /* Check status, the controller may have refused the endpoint creation. */ + if (status != UX_SUCCESS) + + /* An error occurred. The interface cannot be mounted. */ + return(status); + + } + + /* Next interface. */ + interface = interface -> ux_interface_next_interface; + } + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_configuration_instance_delete.c b/common/core/src/ux_host_stack_configuration_instance_delete.c new file mode 100644 index 0000000..e537523 --- /dev/null +++ b/common/core/src/ux_host_stack_configuration_instance_delete.c @@ -0,0 +1,107 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_configuration_instance_delete PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will delete a configuration instance. It does not */ +/* delete configuration container but it deletes all the alternate */ +/* current alternate settings for each interface it owns. */ +/* */ +/* INPUT */ +/* */ +/* configuration Pointer to configuration */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_instance_delete Delete interface instance */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_stack_configuration_instance_delete(UX_CONFIGURATION *configuration) +{ + +UX_INTERFACE *interface; +ULONG current_alternate_setting; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_CONFIGURATION_INSTANCE_DELETE, configuration, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Obtain the first interface for this configuration. */ + interface = configuration -> ux_configuration_first_interface; + + /* In order to keep the compiler happy, we reset the alternate setting. */ + current_alternate_setting = 0; + + /* Each selected alternate setting for each interface must be deleted. */ + while (interface != UX_NULL) + { + + /* If this is the first alternate setting, the current alternate setting is maintained here. */ + if (interface -> ux_interface_descriptor.bAlternateSetting == 0) + { + + current_alternate_setting = interface -> ux_interface_current_alternate_setting; + } + + if (interface -> ux_interface_descriptor.bAlternateSetting == current_alternate_setting) + { + _ux_host_stack_interface_instance_delete(interface); + } + + interface = interface -> ux_interface_next_interface; + } + + return; +} + diff --git a/common/core/src/ux_host_stack_configuration_interface_get.c b/common/core/src/ux_host_stack_configuration_interface_get.c new file mode 100644 index 0000000..6c6362e --- /dev/null +++ b/common/core/src/ux_host_stack_configuration_interface_get.c @@ -0,0 +1,183 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_configuration_interface_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns an interface container based on a */ +/* configuration handle, an interface index and an alternate setting */ +/* index. */ +/* */ +/* INPUT */ +/* */ +/* configuration Pointer to configuration */ +/* interface_index Index of interface */ +/* alternate_setting_index Index of alternate setting */ +/* interface Destination of interface */ +/* pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_configuration_interface_get(UX_CONFIGURATION *configuration, + UINT interface_index, UINT alternate_setting_index, + UX_INTERFACE **interface) +{ + +UINT current_interface_number; +UINT container_index; +UX_INTERFACE *current_interface; + + + /* Do a sanity check on the configuration handle. */ + if (configuration -> ux_configuration_handle != (ULONG) (ALIGN_TYPE) configuration) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, configuration, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Start with the interface attached to the configuration. */ + current_interface = configuration -> ux_configuration_first_interface; + + /* The first interface has the index 0 */ + container_index = 0; + + /* Reset the interface number */ + current_interface_number = 0; + + /* Traverse the list of the interfaces until we found the right one */ + while (current_interface != UX_NULL) + { + + /* Check if the interface index matches the current one. */ + if (interface_index == container_index) + { + + /* We have found the correct interface, now search for the alternate setting. */ + current_interface_number = current_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* The first alternate setting has the index 0. */ + container_index = 0; + + /* Loop on all the alternate settings for this interface. */ + while (current_interface != UX_NULL) + { + + /* Check if the index is matched */ + if (alternate_setting_index == container_index) + { + + /* We have found the right interface/alternate setting combination. Set the + interface return pointer. */ + *interface = current_interface; + + /* Return success to caller. */ + return(UX_SUCCESS); + } + + /* Move to next alternate setting index. */ + container_index++; + + /* Move to the next alternate setting. */ + current_interface = current_interface -> ux_interface_next_interface; + + + /* Check new interface pointer, might be the end. */ + if (current_interface != UX_NULL) + { + + /* And verify that we are still in the same interface. */ + if (current_interface -> ux_interface_descriptor.bInterfaceNumber != current_interface_number) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_INTERFACE_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_INTERFACE_HANDLE_UNKNOWN, interface, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_INTERFACE_HANDLE_UNKNOWN); + } + } + } + } + + /* Check the current interface, we may already be at the end ... */ + if (current_interface != UX_NULL) + { + + /* Move to the next interface. */ + current_interface = current_interface -> ux_interface_next_interface; + + /* Move to the next interface index. */ + container_index++; + } + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_INTERFACE_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_INTERFACE_HANDLE_UNKNOWN, interface, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Didn't find the right interface/alternate setting, return an error! */ + return(UX_INTERFACE_HANDLE_UNKNOWN); +} + diff --git a/common/core/src/ux_host_stack_configuration_set.c b/common/core/src/ux_host_stack_configuration_set.c new file mode 100644 index 0000000..bda29c4 --- /dev/null +++ b/common/core/src/ux_host_stack_configuration_set.c @@ -0,0 +1,155 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_configuration_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a setting of a device configuration. */ +/* If the host is OTG capable and the device has an OTG descriptor */ +/* that supports HNP we perform a SET_FEATURE with b_hnp_support. */ +/* */ +/* INPUT */ +/* */ +/* configuration Pointer to configuration */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_configuration_set(UX_CONFIGURATION *configuration) +{ + +UX_DEVICE *device; +UX_TRANSFER *transfer_request; +UINT status; +UX_ENDPOINT *control_endpoint; +#ifdef UX_OTG_SUPPORT +UX_HCD *hcd; +#endif + + + /* A configuration is selected. Retrieve the pointer to the control endpoint + and its transfer request. */ + device = configuration -> ux_configuration_device; + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + +#ifdef UX_OTG_SUPPORT + /* Check if the configuration has an OTG device with HNP feature. */ + if (configuration -> ux_configuration_otg_capabilities & UX_OTG_HNP_SUPPORT) + { + + /* For HNP to work the device has to be connected directly to the Root Hub and not + a down stream hub. If the parent is NULL, the device is on the root hub. */ + if (device -> ux_device_parent == UX_NULL) + { + + /* With the device we have the pointer to the HCD. */ + hcd = device -> ux_device_hcd; + + /* Check the HCD to ensure we have an OTG host controller. */ + if (hcd -> ux_hcd_otg_capabilities & UX_HCD_OTG_CAPABLE) + { + + /* The Host controller is OTG aware. Perform a SET_FEATURE with b_hnp_support. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_SET_FEATURE; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT| UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_OTG_FEATURE_A_HNP_SUPPORT; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the device fails this command we turn off its OTG capabilities. */ + if (status != UX_SUCCESS) + + /* Reset the OTG capabilities of the device. */ + configuration -> ux_configuration_otg_capabilities = 0; + + } + } + } +#endif + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_CONFIGURATION_SET, configuration, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Create a transfer_request for the SET_CONFIGURATION request. No data for this request. */ + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_SET_CONFIGURATION; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = (USHORT) configuration -> ux_configuration_descriptor.bConfigurationValue; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check completion status. */ + if(status == UX_SUCCESS) + { + + /* Change the device state to configured. */ + device -> ux_device_state = UX_DEVICE_CONFIGURED; + + /* Store the new configuration value in the device container. */ + device -> ux_device_current_configuration = configuration -> ux_configuration_descriptor.bConfigurationValue; + } + + /* Return status to caller. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_delay_ms.c b/common/core/src/ux_host_stack_delay_ms.c new file mode 100644 index 0000000..fa96985 --- /dev/null +++ b/common/core/src/ux_host_stack_delay_ms.c @@ -0,0 +1,74 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_delay_ms PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is now obsolete. */ +/* */ +/* INPUT */ +/* */ +/* time Number of milliseconds to */ +/* wait for */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* (ux_hcd_entry_function) HCD entry function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_stack_delay_ms(ULONG time) +{ + UX_PARAMETER_NOT_USED(time); +} + diff --git a/common/core/src/ux_host_stack_device_address_set.c b/common/core/src/ux_host_stack_device_address_set.c new file mode 100644 index 0000000..436d0e6 --- /dev/null +++ b/common/core/src/ux_host_stack_device_address_set.c @@ -0,0 +1,158 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_device_address_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the device address to the new device. */ +/* */ +/* INPUT */ +/* */ +/* device Pointer to device */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_delay_ms Thread sleep */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_device_address_set(UX_DEVICE *device) +{ + +UX_TRANSFER *transfer_request; +UINT status; +UX_ENDPOINT *control_endpoint; +UX_HCD *hcd; +UINT address_byte_index; +UINT address_bit_index; +UCHAR device_address_byte; +USHORT device_address; + + /* Retrieve the pointer to the control endpoint. */ + control_endpoint = &device -> ux_device_control_endpoint; + + /* Retrieve the transfer request pointer. */ + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* We need the HCD pointer as well. */ + hcd = device -> ux_device_hcd; + + /* Calculate the new address of this device. We start with address 1. */ + device_address = 1; + for (address_byte_index = 0; address_byte_index < 16; address_byte_index++) + { + + /* Get the address mask byte. */ + device_address_byte = hcd -> ux_hcd_address[address_byte_index]; + + /* Scan each bit for an empty spot. */ + for (address_bit_index = 0; address_bit_index < 8; address_bit_index++) + { + + if ((device_address_byte & (1 << address_bit_index)) == 0) + { + + /* We have found an empty spot. Reserve this address. */ + device_address_byte = (UCHAR)((UCHAR)device_address_byte | (UCHAR)(1 << address_bit_index)); + + /* Store the address mask byte. */ + hcd -> ux_hcd_address[address_byte_index] = device_address_byte; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_ADDRESS_SET, device, device_address, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Create a transfer request for the SET_ADDRESS request. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_SET_ADDRESS; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = device_address; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Now, this address will be the one used in future transfers. The transfer may have failed and therefore + all the device resources including the new address will be free.*/ + device -> ux_device_address = (ULONG) device_address; + + /* Check completion status. */ + if (status == UX_SUCCESS) + { + + /* Some devices need some time to accept this address. */ + _ux_utility_delay_ms(UX_DEVICE_ADDRESS_SET_WAIT); + + /* Return successful status. */ + return(status); + } + else + { + + /* We have an error at the first device transaction. This is mostly + due to the device having failed on the reset after power up. + we will try again either at the root hub or regular hub. */ + return(status); + } + } + + /* This address was already taken, increment to the next address. */ + device_address++; + } + } + + /* We should never get here! */ + return(UX_ERROR); +} + diff --git a/common/core/src/ux_host_stack_device_configuration_get.c b/common/core/src/ux_host_stack_device_configuration_get.c new file mode 100644 index 0000000..bdd772c --- /dev/null +++ b/common/core/src/ux_host_stack_device_configuration_get.c @@ -0,0 +1,134 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_device_configuration_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns a configuration container based on a device */ +/* handle and a configuration index. */ +/* */ +/* INPUT */ +/* */ +/* device Pointer to device */ +/* configuration_index Index of configuration */ +/* configuration Pointer to configuration */ +/* destination */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_device_configuration_get(UX_DEVICE *device, UINT configuration_index, + UX_CONFIGURATION **configuration) +{ + +UINT current_configuration_index; +UX_CONFIGURATION *current_configuration; + + /* Do a sanity check on the device handle. */ + if (device -> ux_device_handle != (ULONG) (ALIGN_TYPE) device) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DEVICE_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DEVICE_HANDLE_UNKNOWN); + } + + /* Start with the configuration attached to the device. */ + current_configuration = device -> ux_device_first_configuration; + + /* The first configuration has the index 0. */ + current_configuration_index = 0; + + /* Traverse the list of the configurations until we found the right one. */ + while (current_configuration != UX_NULL) + { + + /* Check if the configuration index matches the current one. */ + if (configuration_index == current_configuration_index) + { + + /* Return the configuration pointer. */ + *configuration = current_configuration; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_CONFIGURATION_GET, device, current_configuration, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Return successful completion. */ + return(UX_SUCCESS); + } + + /* Move to the next configuration. */ + current_configuration = current_configuration -> ux_configuration_next_configuration; + + /* Move to the next index. */ + current_configuration_index++; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, configuration, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); +} + diff --git a/common/core/src/ux_host_stack_device_configuration_reset.c b/common/core/src/ux_host_stack_device_configuration_reset.c new file mode 100644 index 0000000..91f3f50 --- /dev/null +++ b/common/core/src/ux_host_stack_device_configuration_reset.c @@ -0,0 +1,123 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_device_configuration_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function resets the configuration of the device to zero. */ +/* */ +/* INPUT */ +/* */ +/* configuration Pointer to configuration */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_instance_delete */ +/* Delete configuration instance*/ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_device_configuration_reset(UX_DEVICE *device) +{ + +UX_TRANSFER *transfer_request; +UX_ENDPOINT *control_endpoint; +UX_CONFIGURATION *current_configuration; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_CONFIGURATION_SELECT, device, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* A configuration is selected. Retrieve the pointer to the control endpoint + and its transfer request. */ + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Check for the state of the device . If the device is already configured, + we need to cancel the existing configuration before resetting it. */ + if (device -> ux_device_state == UX_DEVICE_CONFIGURED) + { + + /* The device is configured. Get the first configuration pointer. */ + current_configuration = device -> ux_device_first_configuration; + + /* Traverse the configuration list until we find the right one. */ + while (current_configuration -> ux_configuration_descriptor.bConfigurationValue != + device -> ux_device_current_configuration) + { + + current_configuration = current_configuration -> ux_configuration_next_configuration; + } + + /* Deselect this instance */ + _ux_host_stack_configuration_instance_delete(current_configuration); + } + + /* Set state of device to ATTACHED. */ + device -> ux_device_state = UX_DEVICE_ATTACHED; + + /* Create a transfer_request for the SET_CONFIGURATION request. No data for this request. */ + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_SET_CONFIGURATION; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Return status. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_device_configuration_select.c b/common/core/src/ux_host_stack_device_configuration_select.c new file mode 100644 index 0000000..7d66915 --- /dev/null +++ b/common/core/src/ux_host_stack_device_configuration_select.c @@ -0,0 +1,160 @@ + + + + + + + + +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_device_configuration_select PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function selects a specific configuration for a device. */ +/* When this configuration is set to the device, by default all the */ +/* device interface and their associated alternate setting 0 is */ +/* activated on the device. If the device/interface class driver */ +/* wishes to change the setting of a particular interface, it needs */ +/* to issue a select interface setting function. */ +/* */ +/* INPUT */ +/* */ +/* configuration Pointer to configuration */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_instance_create Create configuration */ +/* instance */ +/* _ux_host_stack_configuration_instance_delete Delete configuration */ +/* instance */ +/* _ux_host_stack_configuration_set Set configuration */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_device_configuration_select(UX_CONFIGURATION *configuration) +{ + +UX_DEVICE *device; +UX_CONFIGURATION *current_configuration; +UINT status; + + /* Check for validity of the configuration handle. */ + if (configuration -> ux_configuration_handle != (ULONG) (ALIGN_TYPE) configuration) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, configuration, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Get the device container for this configuration. */ + device = configuration -> ux_configuration_device; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_CONFIGURATION_SELECT, device, configuration, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Check for the state of the device . If the device is already configured, + we need to cancel the existing configuration before enabling this one. */ + if (device -> ux_device_state == UX_DEVICE_CONFIGURED) + { + + /* The device is configured. Get the first configuration pointer. */ + current_configuration = device -> ux_device_first_configuration; + + /* Traverse the configuration list until we find the right one. */ + while (current_configuration -> ux_configuration_descriptor.bConfigurationValue != + device -> ux_device_current_configuration) + { + + current_configuration = current_configuration -> ux_configuration_next_configuration; + } + + /* Deselect this instance */ + _ux_host_stack_configuration_instance_delete(current_configuration); + } + + /* The device is now in the unconfigured state. We need to deal + with the amount of power the device is consuming before allowing + it to be configured. Otherwise we may run the risk of an over + current fault. */ + if (configuration -> ux_configuration_descriptor.MaxPower > device -> ux_device_max_power) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_OVER_CURRENT_CONDITION); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_OVER_CURRENT_CONDITION, configuration, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_OVER_CURRENT_CONDITION); + } + + /* The device can now be configured. */ + status = _ux_host_stack_configuration_set(configuration); + if (status != UX_SUCCESS) + return(status); + + /* Create the configuration instance. */ + status = _ux_host_stack_configuration_instance_create(configuration); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_device_descriptor_read.c b/common/core/src/ux_host_stack_device_descriptor_read.c new file mode 100644 index 0000000..968155e --- /dev/null +++ b/common/core/src/ux_host_stack_device_descriptor_read.c @@ -0,0 +1,164 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_device_descriptor_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads the device descriptor. */ +/* */ +/* INPUT */ +/* */ +/* device Pointer to device */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_device_descriptor_read(UX_DEVICE *device) +{ + +UX_TRANSFER *transfer_request; +UINT status; +UCHAR * descriptor; +UX_ENDPOINT *control_endpoint; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_DESCRIPTOR_READ, device, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Retrieve the pointer to the control endpoint. */ + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the descriptor. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_DEVICE_DESCRIPTOR_LENGTH); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Create a transfer_request for the GET_DESCRIPTOR request. The first transfer_request asks + for the first 8 bytes only. This way we will know the real MaxPacketSize + value for the control endpoint. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = 8; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_DEVICE_DESCRIPTOR_ITEM << 8; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 8)) + { + + /* Parse the device descriptor and create the local descriptor. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_device_descriptor_structure, UX_DEVICE_DESCRIPTOR_ENTRIES, + (UCHAR *) &device -> ux_device_descriptor); + } + else + { + + /* Free all used resources. */ + _ux_utility_memory_free(descriptor); + + /* Return completion status. */ + return(status); + } + + /* Update the max packet size value for the endpoint. */ + control_endpoint -> ux_endpoint_descriptor.wMaxPacketSize = device -> ux_device_descriptor.bMaxPacketSize0; + + /* Create a transfer_request for the GET_DESCRIPTOR request. This time, we have the complete length */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = UX_DEVICE_DESCRIPTOR_LENGTH; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_DEVICE_DESCRIPTOR_ITEM << 8; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == UX_DEVICE_DESCRIPTOR_LENGTH)) + { + + /* Parse the device descriptor and create the local descriptor. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_device_descriptor_structure, UX_DEVICE_DESCRIPTOR_ENTRIES, + (UCHAR *) &device -> ux_device_descriptor); + } + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* The device descriptor does not contain the right amount of data. Maybe corruption. */ + status = UX_DESCRIPTOR_CORRUPTED; + } + + /* Free all used resources. */ + _ux_utility_memory_free(descriptor); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_device_get.c b/common/core/src/ux_host_stack_device_get.c new file mode 100644 index 0000000..d323ff5 --- /dev/null +++ b/common/core/src/ux_host_stack_device_get.c @@ -0,0 +1,133 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_device_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns a device container based on its index. The */ +/* device index start with device 0. Note that the index is a ULONG */ +/* because we could have several controllers and a byte index might */ +/* not be enough. */ +/* */ +/* INPUT */ +/* */ +/* device_index Index of device */ +/* device Destination for device pointer*/ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_device_get(ULONG device_index, UX_DEVICE **device) +{ + +UX_DEVICE *current_device; +ULONG current_device_index; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_GET, device_index, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Check if the device index is still within the limits. */ + if (device_index >= _ux_system_host -> ux_system_host_max_devices) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DEVICE_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DEVICE_HANDLE_UNKNOWN); + } + + /* Start with the first device. */ + current_device = _ux_system_host -> ux_system_host_device_array; + current_device_index = 0; + + /* Search the list until the end. */ + while (current_device_index < _ux_system_host -> ux_system_host_max_devices) + { + + /* Check to see if this device is existing. */ + if (current_device -> ux_device_handle != UX_UNUSED) + { + + /* Have we reached the index we are looking for? */ + if (device_index == current_device_index) + { + + /* Yes, return the device pointer. */ + *device = current_device; + + /* Return successful completion. */ + return(UX_SUCCESS); + } + } + + /* Move to next device index. */ + current_device_index++; + + /* Move to next device. */ + current_device++; + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error. */ + return(UX_DEVICE_HANDLE_UNKNOWN); +} + diff --git a/common/core/src/ux_host_stack_device_remove.c b/common/core/src/ux_host_stack_device_remove.c new file mode 100644 index 0000000..f82e923 --- /dev/null +++ b/common/core/src/ux_host_stack_device_remove.c @@ -0,0 +1,192 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_device_remove PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will remove a USB device from the bus. */ +/* */ +/* INPUT */ +/* */ +/* HCD Pointer to the HCD */ +/* parent The parent device address */ +/* port_index Index of the port on which the*/ +/* change of status occurred */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_device_resources_free Free all device resources */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_device_remove(UX_HCD *hcd, UX_DEVICE *parent, UINT port_index) +{ + +ULONG container_index; +UX_DEVICE *device; +UX_CONFIGURATION *configuration; +UX_INTERFACE *interface; +UX_HOST_CLASS_COMMAND command; + + /* We need to find the device descriptor for the removed device. We can find it + with the parent device and the port it was attached to. Start with the first device. */ + device = _ux_system_host -> ux_system_host_device_array; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_REMOVE, hcd, parent, port_index, device, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* If trace is enabled, unregister this object. */ + UX_TRACE_OBJECT_UNREGISTER(device); + + /* Start at the beginning of the list. */ + container_index = 0; + + /* Search the list until the end. */ + while (container_index++ < _ux_system_host -> ux_system_host_max_devices) + { + + /* Until we have found a used entry. */ + if (device -> ux_device_handle != UX_UNUSED) + { + + /* Check for the parent device and the port location and the controller. */ + if((device -> ux_device_parent == parent) && (device -> ux_device_port_location == port_index) && + (device -> ux_device_hcd == hcd)) + { + + /* We have found the device to be removed. */ + device -> ux_device_state = UX_DEVICE_REMOVED; + + /* We have found the device to be removed. Initialize the class + command with the generic parameters. */ + command.ux_host_class_command_request = UX_HOST_CLASS_COMMAND_DEACTIVATE; + + /* The device may have a class associated with the device container or its interfaces. */ + if (device -> ux_device_class_instance != UX_NULL) + { + + /* We need to stop the class instance for the device. */ + command.ux_host_class_command_instance = device -> ux_device_class_instance; + + /* Call the class. */ + device -> ux_device_class -> ux_host_class_entry_function(&command); + } + else + { + + /* Search for the active configuration. */ + configuration = device -> ux_device_first_configuration; + + /* Parse the interface(s) for this device in search of the classes + who own this device. */ + while (configuration != UX_NULL) + { + + /* Is this the correct configuration? */ + if (configuration -> ux_configuration_descriptor.bConfigurationValue == + device -> ux_device_current_configuration) + { + + /* We have the correct configuration, search the interface(s). */ + interface = configuration -> ux_configuration_first_interface; + + /* Loop to perform the search. */ + while (interface != UX_NULL) + { + + /* Check if an instance of the interface is present. */ + if (interface -> ux_interface_class_instance != UX_NULL) + { + + /* We need to stop the class instance for the device. */ + command.ux_host_class_command_instance = interface -> ux_interface_class_instance; + + /* Call the class. */ + interface -> ux_interface_class -> ux_host_class_entry_function(&command); + } + + /* Move to next interface. */ + interface = interface -> ux_interface_next_interface; + } + } + + /* Move to next configuration in the list. */ + configuration = configuration -> ux_configuration_next_configuration; + } + } + + /* Now all the resources for this device must be free. */ + _ux_host_stack_device_resources_free(device); + + /* Decrement the number of devices on this bus. */ + hcd -> ux_hcd_nb_devices--; + + /* We are done with this device removal. */ + return(UX_SUCCESS); + } + } + + /* Move to the next device entry. */ + device++; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DEVICE_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We get here when we could not find the device. */ + return(UX_DEVICE_HANDLE_UNKNOWN); +} + diff --git a/common/core/src/ux_host_stack_device_resources_free.c b/common/core/src/ux_host_stack_device_resources_free.c new file mode 100644 index 0000000..050f970 --- /dev/null +++ b/common/core/src/ux_host_stack_device_resources_free.c @@ -0,0 +1,216 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_device_resources_free PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will free all the device resources allocated. */ +/* */ +/* INPUT */ +/* */ +/* device Device pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort transfer */ +/* _ux_host_stack_endpoint_instance_delete */ +/* Delete endpoint instance */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_memory_set Set memory with a value */ +/* _ux_utility_semaphore_delete Semaphore delete */ +/* _ux_utility_thread_schedule_other Sleep thread to let others */ +/* run */ +/* (ux_hcd_entry_function) HCD entry function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_device_resources_free(UX_DEVICE *device) +{ + +UX_CONFIGURATION *configuration; +UX_INTERFACE *interface; +UX_ENDPOINT *endpoint; +VOID *container; +ULONG current_alternate_setting; +UX_HCD *hcd; +UINT device_address_byte_index; +UINT device_address_bit_index; +UCHAR device_address_byte; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_DEVICE_RESOURCE_FREE, device, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Set the alternate setting to zero. */ + current_alternate_setting = 0; + + /* Get the first configuration registered to the device. */ + configuration = device -> ux_device_first_configuration; + + /* Parse all the configurations, remove all resources for the possible configuration. */ + while (configuration != UX_NULL) + { + + /* We have the correct configuration, search the interface(s). */ + interface = configuration -> ux_configuration_first_interface; + + /* Parse all the interfaces. */ + while (interface != UX_NULL) + { + + /* The alternate setting 0 has the selected alternate setting value. */ + if (interface -> ux_interface_descriptor.bAlternateSetting == 0) + current_alternate_setting = interface -> ux_interface_current_alternate_setting; + + /* If this is the selected interface, we need to free all the endpoints + attached to the alternate setting for this interface. */ + endpoint = interface -> ux_interface_first_endpoint; + + /* Parse all the endpoints. */ + while (endpoint != UX_NULL) + { + + /* Check if this is the selected interface. */ + if (interface -> ux_interface_descriptor.bAlternateSetting == current_alternate_setting) + { + + /* Delete the endpoint instance first. */ + _ux_host_stack_endpoint_instance_delete(endpoint); + } + + /* Memorize the endpoint container address. */ + container = (VOID *) endpoint; + + /* Get the next endpoint. */ + endpoint = endpoint -> ux_endpoint_next_endpoint; + + /* Delete the endpoint container. */ + _ux_utility_memory_free(container); + } + + + /* Memorize the interface container address. */ + container = (VOID *) interface; + + /* Get the next interface. */ + interface = interface -> ux_interface_next_interface; + + /* Delete the interface container. */ + _ux_utility_memory_free(container); + } + + /* Memorize this configuration address before we free it. */ + container = (VOID *) configuration; + + /* Move to the next configuration in the list. */ + configuration = configuration -> ux_configuration_next_configuration; + + /* Free the configuration. */ + _ux_utility_memory_free(container); + } + + /* We need the HCD address for the control endpoint removal and to free + the device address. */ + hcd = device -> ux_device_hcd; + + /* Was the control endpoint already created ? */ + if (device -> ux_device_control_endpoint.ux_endpoint_state != 0) + { + + /* There may be pending transactions on the control endpoint. They need to be aborted. */ + _ux_host_stack_endpoint_transfer_abort(&device -> ux_device_control_endpoint); + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + the control endpoint to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* The control endpoint should be destroyed at the HCD level. */ + hcd -> ux_hcd_entry_function(hcd, UX_HCD_DESTROY_ENDPOINT, (VOID *) &device -> ux_device_control_endpoint); + } + + /* The semaphore attached to the control endpoint must be destroyed. */ + _ux_utility_semaphore_delete(&device -> ux_device_control_endpoint.ux_endpoint_transfer_request.ux_transfer_request_semaphore); + + /* Check if the device had an assigned address. */ + if (device -> ux_device_address != 0) + { + + /* The USB address of this device can now be returned to the pool + We need the HCD pointer for this operation. */ + + /* Calculate in which byte index the device address belongs. */ + device_address_byte_index = (UINT) (device -> ux_device_address-1)/8; + + /* Now calculate the amount left in the byte index in bit. */ + device_address_bit_index = (UINT) (device -> ux_device_address-1)%8; + + /* Build the mask for the address. */ + device_address_byte = (UCHAR)(1 << device_address_bit_index); + + /* Free the address. */ + hcd -> ux_hcd_address[device_address_byte_index] &= (UCHAR)~device_address_byte; + } + + /* The semaphore for endpoint 0 protection must be destroyed. */ + _ux_utility_semaphore_delete(&device -> ux_device_protection_semaphore); + + /* Now this device can be free and its container return to the pool. */ + _ux_utility_memory_set(device, 0, sizeof(UX_DEVICE)); + + /* Mark the device handle as unused. */ + device -> ux_device_handle = UX_UNUSED; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_endpoint_instance_create.c b/common/core/src/ux_host_stack_endpoint_instance_create.c new file mode 100644 index 0000000..f24a8c4 --- /dev/null +++ b/common/core/src/ux_host_stack_endpoint_instance_create.c @@ -0,0 +1,152 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_endpoint_instance_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will create an endpoint instance. The HCD layer is */ +/* invoked to create each endpoint and the bandwidth claimed by each */ +/* endpoint is allocated. */ +/* */ +/* INPUT */ +/* */ +/* endpoint Endpoint to delete */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_bandwidth_check Check bandwidth */ +/* _ux_host_stack_bandwidth_claim Claim bandwidth */ +/* _ux_utility_semaphore_create Semaphore create */ +/* (ux_hcd_entry_function) HCD entry function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_endpoint_instance_create(UX_ENDPOINT *endpoint) +{ + +UX_HCD *hcd; +UX_DEVICE *device; +UINT status; +UCHAR endpoint_type; + + + /* Obtain the HCD for this endpoint. */ + device = endpoint -> ux_endpoint_device; + hcd = device -> ux_device_hcd; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_ENDPOINT_INSTANCE_CREATE, device, endpoint, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + + /* If the endpoint needs guaranteed bandwidth, check if we have enough */ + endpoint_type = (endpoint -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE; + switch (endpoint_type) + { + + case UX_CONTROL_ENDPOINT: + case UX_BULK_ENDPOINT: + + break; + + default: + + /* Check the bandwidth for this endpoint */ + if (_ux_host_stack_bandwidth_check(hcd, endpoint) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_NO_BANDWIDTH_AVAILABLE); + + return(UX_NO_BANDWIDTH_AVAILABLE); + } + + + break; + } + + /* Create this endpoint. */ + status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_CREATE_ENDPOINT, (VOID *) endpoint); + + /* Check status. */ + if (status != UX_SUCCESS) + { + + /* Return completion status. */ + return(status); + } + + /* Claim bandwidth if needed. */ + if ((endpoint_type == UX_INTERRUPT_ENDPOINT) || (endpoint_type == UX_ISOCHRONOUS_ENDPOINT)) + { + + /* Claim its bandwidth */ + _ux_host_stack_bandwidth_claim(hcd, endpoint); + } + + /* Create a semaphore for this endpoint to be attached to its transfer request. */ + status = _ux_utility_semaphore_create(&endpoint -> ux_endpoint_transfer_request.ux_transfer_request_semaphore, + "ux_transfer_request_semaphore", 0); + + /* Check status. */ + if (status == UX_SUCCESS) + { + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_ENDPOINT, endpoint, 0, 0, 0) + + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_endpoint_instance_delete.c b/common/core/src/ux_host_stack_endpoint_instance_delete.c new file mode 100644 index 0000000..66e69a9 --- /dev/null +++ b/common/core/src/ux_host_stack_endpoint_instance_delete.c @@ -0,0 +1,119 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_endpoint_instance_delete PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will delete an endpoint instance. It does not delete */ +/* the endpoint container but it removes the HCD endpoint and reclaims */ +/* the bandwidth. */ +/* */ +/* INPUT */ +/* */ +/* endpoint Endpoint to delete */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_bandwidth_release Release bandwidth */ +/* _ux_utility_semaphore_delete Semaphore delete */ +/* (ux_hcd_entry_function) HCD entry function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_stack_endpoint_instance_delete(UX_ENDPOINT *endpoint) +{ + +UX_HCD *hcd; +UX_DEVICE *device; + + + /* Obtain the HCD for this endpoint. */ + device = endpoint -> ux_endpoint_device; + hcd = device -> ux_device_hcd; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_ENDPOINT_INSTANCE_DELETE, device, endpoint, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Ensure the endpoint had its physical ED allocated. */ + if (endpoint -> ux_endpoint_ed != UX_NULL) + { + + /* Destroy this endpoint. */ + hcd -> ux_hcd_entry_function(hcd, UX_HCD_DESTROY_ENDPOINT, (VOID *) endpoint); + + /* Free the semaphore previously attached to the transfer_request of this endpoint. */ + _ux_utility_semaphore_delete(&endpoint -> ux_endpoint_transfer_request.ux_transfer_request_semaphore); + } + + /* If the endpoint requested guaranteed bandwidth, free it now. */ + switch ((endpoint -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + case UX_BULK_ENDPOINT: + + break; + + default: + + /* Reclaim its bandwidth. */ + _ux_host_stack_bandwidth_release(hcd, endpoint); + } + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(endpoint); + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_host_stack_endpoint_reset.c b/common/core/src/ux_host_stack_endpoint_reset.c new file mode 100644 index 0000000..78753de --- /dev/null +++ b/common/core/src/ux_host_stack_endpoint_reset.c @@ -0,0 +1,118 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_endpoint_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function resets an endpoint after a stall or other error */ +/* condition. */ +/* */ +/* INPUT */ +/* */ +/* endpoint Endpoint to abort transfer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Send transfer request */ +/* (ux_hcd_entry_function) HCD entry function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_endpoint_reset(UX_ENDPOINT *endpoint) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UX_DEVICE *device; +UX_HCD *hcd; +UINT status; + + + /* Get the device container from the endpoint */ + device = endpoint -> ux_endpoint_device; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_ENDPOINT_RESET, device, endpoint, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Get the control endpoint attached to the device. */ + control_endpoint = &device -> ux_device_control_endpoint; + + /* Retrieve the transfer_request pointer. */ + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Create a transfer_request for the CLEAR_FEATURE request. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_CLEAR_FEATURE; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT| UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_ENDPOINT; + transfer_request -> ux_transfer_request_value = UX_ENDPOINT_HALT; + transfer_request -> ux_transfer_request_index = endpoint -> ux_endpoint_descriptor.bEndpointAddress; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Reset the endpoint at the HCD level. */ + if (status == UX_SUCCESS) + { + + /* Pickup HCD pointer. */ + hcd = device -> ux_device_hcd; + + /* Call HCD entry function. */ + status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_RESET_ENDPOINT, endpoint); + } + + /* And return the completion status. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_endpoint_transfer_abort.c b/common/core/src/ux_host_stack_endpoint_transfer_abort.c new file mode 100644 index 0000000..f0b7ed5 --- /dev/null +++ b/common/core/src/ux_host_stack_endpoint_transfer_abort.c @@ -0,0 +1,92 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_endpoint_transfer_abort PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cancel all the transfer_requests attached to an */ +/* endpoint. The endpoint is not reset and its toggle state is left */ +/* the same. */ +/* */ +/* In this version of USBX, there can only be one transfer request */ +/* pending for an endpoint. It is not known at this stage if having */ +/* multiple transfer request is a benefit for USBX but this function */ +/* may be changed one day to add such functionality. */ +/* */ +/* INPUT */ +/* */ +/* endpoint Endpoint to abort transfer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request_abort Transfer request abort */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_endpoint_transfer_abort(UX_ENDPOINT *endpoint) +{ + +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_ENDPOINT_TRANSFER_ABORT, endpoint, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Since we only have one transfer_request per endpoint, use the regular + abort transfer request function. */ + status = _ux_host_stack_transfer_request_abort(&endpoint -> ux_endpoint_transfer_request); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_enum_thread_entry.c b/common/core/src/ux_host_stack_enum_thread_entry.c new file mode 100644 index 0000000..29d6e8a --- /dev/null +++ b/common/core/src/ux_host_stack_enum_thread_entry.c @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_enum_thread_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains the enum thread for USBX. It is in charge of */ +/* the topology changes either from device insertion\extraction on */ +/* the root hub or on a regular hub. */ +/* */ +/* This thread ensures we never have more that 2 instances trying to */ +/* perform a change to the topology (mostly enumeration) for fear that */ +/* more than one device could answer to address 0. */ +/* */ +/* This function is the entry point of the topology thread. It waits */ +/* until one of the HCDs or a hub sets the semaphore to indicate */ +/* there has been a change in the USB topology which could be either */ +/* a insertion or extraction or eventually a hub downstream port */ +/* signal. */ +/* */ +/* INPUT */ +/* */ +/* input Not used input */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_rh_change_process Root hub processing */ +/* _ux_utility_semaphore_get Get signal semaphore */ +/* (ux_system_host_enum_hub_function) HUB enum processing function */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_stack_enum_thread_entry(ULONG input) +{ + + UX_PARAMETER_NOT_USED(input); + + /* Loop forever waiting for changes signaled through the semaphore. */ + while (1) + { + + /* Wait for the semaphore to be put by the root hub or a regular hub. */ + _ux_utility_semaphore_get(&_ux_system_host -> ux_system_host_enum_semaphore, UX_WAIT_FOREVER); + + /* We try the hub first. For this we look into the USBX project + structure to see if there is at least one hub. */ + if (_ux_system_host -> ux_system_host_enum_hub_function != UX_NULL) + { + + /* Yes, there is a HUB function, call it! */ + _ux_system_host -> ux_system_host_enum_hub_function(); + } + + /* The signal may be also coming from the root hub, call the root hub handler. */ + _ux_host_stack_rh_change_process(); + } +} + diff --git a/common/core/src/ux_host_stack_hcd_register.c b/common/core/src/ux_host_stack_hcd_register.c new file mode 100644 index 0000000..5aa1b3e --- /dev/null +++ b/common/core/src/ux_host_stack_hcd_register.c @@ -0,0 +1,135 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_hcd_register PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers a USB controller driver with the USBX stack */ +/* and invokes the HCD driver's initialization function. */ +/* */ +/* Note: The C string of hcd_name must be NULL-terminated and the */ +/* length of it (without the NULL-terminator itself) must be no larger */ +/* than UX_MAX_HCD_NAME_LENGTH. */ +/* */ +/* INPUT */ +/* */ +/* hcd_name Name of HCD to register */ +/* hcd_entry_function Entry function of HCD driver */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_string_length_check Check and return C string */ +/* length if no error */ +/* _ux_utility_memory_copy Copy name into HCD structure */ +/* (hcd_init_function) Init function of HCD driver */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_hcd_register(UCHAR *hcd_name, + UINT (*hcd_init_function)(struct UX_HCD_STRUCT *), ULONG hcd_param1, ULONG hcd_param2) +{ + +UX_HCD *hcd; +ULONG hcd_index; +UINT status; +UINT hcd_name_length = 0; + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_HCD_REGISTER, hcd_name, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Get the length of the class name (exclude null-terminator). */ + status = _ux_utility_string_length_check(hcd_name, &hcd_name_length, UX_MAX_HCD_NAME_LENGTH); + if (status) + return(status); + + /* We need to parse the controller driver table to find an empty spot. */ + hcd = _ux_system_host -> ux_system_host_hcd_array; + for(hcd_index = 0; hcd_index < _ux_system_host -> ux_system_host_max_hcd; hcd_index++) + { + + /* Is this slot available? */ + if(hcd -> ux_hcd_status == UX_UNUSED) + { + + /* Yes, setup the new HCD entry. */ + + /* Initialize the array of the new controller with its name (include null-terminator). */ + _ux_utility_memory_copy(hcd -> ux_hcd_name, hcd_name, hcd_name_length + 1); + + /* Store the hardware resources of the controller */ + hcd -> ux_hcd_io = hcd_param1; + hcd -> ux_hcd_irq = hcd_param2; + + /* This controller is now used */ + hcd -> ux_hcd_status = UX_USED; + + /* And we have one new controller registered. */ + _ux_system_host -> ux_system_host_registered_hcd++; + + /* We are now calling the HCD driver initialization. */ + status = hcd_init_function(hcd); + + /* Return the completion status to the caller. */ + return(status); + } + + /* Try the next HCD structure */ + hcd++; + } + + /* We have exhausted the array of the HCDs, return an error. */ + return(UX_MEMORY_INSUFFICIENT); +} + diff --git a/common/core/src/ux_host_stack_hcd_thread_entry.c b/common/core/src/ux_host_stack_hcd_thread_entry.c new file mode 100644 index 0000000..cc01793 --- /dev/null +++ b/common/core/src/ux_host_stack_hcd_thread_entry.c @@ -0,0 +1,112 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_hcd_thread_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the host controller thread. */ +/* The HCD thread is initialized at the system level and the thread */ +/* entry routine is invoked right away. This thread suspends until */ +/* one of the HCD resumes it due to HCD activities. */ +/* */ +/* INPUT */ +/* */ +/* input Not used input */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_semaphore_get Get signal semaphore */ +/* (ux_hcd_entry_function) HCD's entry function */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_stack_hcd_thread_entry(ULONG input) +{ + +UINT hcd_index; +UX_HCD *hcd; +UX_INT_SAVE_AREA + + UX_PARAMETER_NOT_USED(input); + + /* Loop forever on the semaphore. The semaphore is used to signal that + there is work for one or more HCDs. */ + while (1) + { + + /* Get the semaphore that signals something is available for this + thread to process. */ + _ux_utility_semaphore_get(&_ux_system_host -> ux_system_host_hcd_semaphore, UX_WAIT_FOREVER); + + /* This thread was awaken by one or more HCD controllers. Check each of the HCDs + to see who posted work to do. */ + for(hcd_index = 0; hcd_index < _ux_system_host -> ux_system_host_registered_hcd; hcd_index++) + { + + /* Pickup HCD pointer. */ + hcd = &_ux_system_host -> ux_system_host_hcd_array[hcd_index]; + + /* Is there work to do for this HCD? */ + if((hcd -> ux_hcd_status == UX_HCD_STATUS_OPERATIONAL) && (hcd -> ux_hcd_thread_signal !=0)) + { + + /* Yes, call the HCD function to process the work. */ + hcd -> ux_hcd_entry_function(hcd, UX_HCD_PROCESS_DONE_QUEUE, UX_NULL); + UX_DISABLE_INTS + hcd -> ux_hcd_thread_signal--; + UX_RESTORE_INTS + } + } + } +} + diff --git a/common/core/src/ux_host_stack_hcd_transfer_request.c b/common/core/src/ux_host_stack_hcd_transfer_request.c new file mode 100644 index 0000000..02bfe6a --- /dev/null +++ b/common/core/src/ux_host_stack_hcd_transfer_request.c @@ -0,0 +1,91 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_hcd_transfer_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will route the transfer_request to the appropriate */ +/* HCD for transfer. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_hcd_entry_function) HCD's entry function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_hcd_transfer_request(UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_DEVICE *device; +UINT status; +UX_HCD *hcd; + + /* Get the endpoint container from the transfer request. */ + endpoint = transfer_request -> ux_transfer_request_endpoint; + + /* Obtain the HCD for this endpoint. */ + device = endpoint -> ux_endpoint_device; + hcd = device -> ux_device_hcd; + + /* Call the HCD entry function to process the transfer request. */ + status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_TRANSFER_REQUEST, (VOID *) transfer_request); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_hnp_polling_thread_entry.c b/common/core/src/ux_host_stack_hnp_polling_thread_entry.c new file mode 100644 index 0000000..d01d2da --- /dev/null +++ b/common/core/src/ux_host_stack_hnp_polling_thread_entry.c @@ -0,0 +1,232 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_hnp_polling_thread_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is awaken every 2 seconds to check if there is a */ +/* OTG device on the bus and if so perform a GET_STATUS as the device */ +/* may request a change of role. */ +/* */ +/* INPUT */ +/* */ +/* none */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_utility_thread_sleep Sleep thread */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_host_stack_role_swap Swapping role */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_stack_hnp_polling_thread_entry(ULONG argument) +{ + +UINT hcd_index; +UX_DEVICE *device; +UX_CONFIGURATION *configuration; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UX_HCD *hcd; +UCHAR *otg_status; +ULONG port_index; +ULONG port_status; +ULONG container_index; +UINT status; + + UX_PARAMETER_NOT_USED(argument); + + /* This thread goes on forever once started. */ + while(1) + { + + /* We need to wake every 2 seconds or so. */ + _ux_utility_thread_sleep(UX_OTG_HNP_THREAD_SLEEP_TIME); + + /* We need to parse the controller driver table to find all controllers that registered + as OTG. */ + for (hcd_index = 0; hcd_index < _ux_system_host -> ux_system_host_registered_hcd; hcd_index++) + { + + /* Pickup HCD pointer. */ + hcd = &_ux_system_host -> ux_system_host_hcd_array[hcd_index]; + + /* Check type of controller. Is it OTG capable ? Must be operational too. */ + if ((hcd -> ux_hcd_otg_capabilities & UX_HCD_OTG_CAPABLE) && + (hcd -> ux_hcd_status == UX_HCD_STATUS_OPERATIONAL)) + { + + /* Yes, we can parse the root hub and see if any devices attached to it. */ + for (port_index = 0; port_index < hcd -> ux_hcd_nb_root_hubs; port_index++) + { + + /* Call HCD for port status. */ + port_status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_GET_PORT_STATUS, (VOID *)((ALIGN_TYPE)port_index)); + + /* Check return status. */ + if (port_status != UX_PORT_INDEX_UNKNOWN) + { + + /* the port_status value is valid and will tell us if there is + a device attached\detached on the downstream port and if the port is powered. */ + if ((port_status & UX_PS_CCS) && (port_status & UX_PS_PPS)) + { + + /* There is a device attached to one of the root hub port. Parse the device + to find out which one it is. */ + device = _ux_system_host -> ux_system_host_device_array; + + /* Start at the beginning of the list. */ + container_index = 0; + + /* Search the list until the end. */ + while (container_index++ < _ux_system_host -> ux_system_host_max_devices) + { + + /* Until we have found a used entry. */ + if (device -> ux_device_handle != UX_UNUSED) + { + + /* Check for the parent device and the port location and the controller. */ + if((device -> ux_device_port_location == port_index) && + (device -> ux_device_hcd == hcd)) + { + + /* We have a device on a OTG port. But is it a OTG HNP capable device ? + We need to parse the configuration until we find the one current. */ + configuration = device -> ux_device_first_configuration; + + /* Are we at the of the configuration list ? */ + while (configuration != UX_NULL) + { + + /* Is this the current configuration ? */ + if (configuration -> ux_configuration_descriptor.bConfigurationValue == + device -> ux_device_current_configuration) + { + + /* Check for OTG HNP support. */ + if (configuration -> ux_configuration_otg_capabilities & UX_OTG_HNP_SUPPORT) + { + + /* Allocate memory for the OTG status. */ + otg_status = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 16); + + /* Check for status. */ + if (otg_status == UX_NULL) + return; + + /* Retrieve the control endpoint and the transfer request associated with it. */ + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Perform a GET_STATUS on this device to see if it wants to become the host. */ + /* Create a transfer_request for the SET_CONFIGURATION request. No data for this request. */ + transfer_request -> ux_transfer_request_data_pointer = otg_status; + transfer_request -> ux_transfer_request_requested_length = 1; + transfer_request -> ux_transfer_request_function = UX_GET_STATUS; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = UX_OTG_STATUS_SELECTOR; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check completion status. */ + if(status == UX_SUCCESS && transfer_request -> ux_transfer_request_actual_length == 1) + { + + /* We have an answer from the device. Check the HNP flag. */ + if (*otg_status & UX_OTG_HOST_REQUEST_FLAG) + { + + /* The device has requested a Host swap. Initiate the command and perform the + stopping of the host. */ + _ux_host_stack_role_swap(device); + } + + } + + /* Free all used resources. */ + _ux_utility_memory_free(otg_status); + + } + } + + /* Move to next configuration in the list. */ + configuration = configuration -> ux_configuration_next_configuration; + + } + } + } + + /* Move to the next device entry. */ + device++; + + } + } + } + } + } + } + } +} + diff --git a/common/core/src/ux_host_stack_initialize.c b/common/core/src/ux_host_stack_initialize.c new file mode 100644 index 0000000..f8b6072 --- /dev/null +++ b/common/core/src/ux_host_stack_initialize.c @@ -0,0 +1,345 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + +UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_HCD), UX_MAX_HCD), UX_MAX_HCD_mul_ovf) +UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_HOST_CLASS), UX_MAX_CLASS_DRIVER), UX_MAX_CLASS_DRIVER_mul_ovf) +UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_DEVICE), UX_MAX_DEVICES), UX_MAX_DEVICES_mul_ovf) + +#ifndef UX_HOST_HNP_POLLING_THREAD_STACK_SIZE +#define UX_HOST_HNP_POLLING_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE +#endif + +/* Defined USBX host variables. */ + +UX_SYSTEM_HOST *_ux_system_host; + +/* Define table of periodic tree entries, properly indexed. */ + +UINT _ux_system_host_hcd_periodic_tree_entries[32] = { + 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c, + 0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e, + 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d, + 0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f}; + +/* Define the names of all the USB Classes of USBX. */ + +UCHAR _ux_system_host_class_hub_name[] = "ux_host_class_hub"; +UCHAR _ux_system_host_class_printer_name[] = "ux_host_class_printer"; +UCHAR _ux_system_host_class_storage_name[] = "ux_host_class_storage"; +UCHAR _ux_system_host_class_hid_name[] = "ux_host_class_hid"; +UCHAR _ux_system_host_class_audio_name[] = "ux_host_class_audio"; +UCHAR _ux_system_host_class_cdc_acm_name[] = "ux_host_class_cdc_acm"; +UCHAR _ux_system_host_class_cdc_dlc_name[] = "ux_host_class_cdc_dlc"; +UCHAR _ux_system_host_class_cdc_ecm_name[] = "ux_host_class_cdc_ecm"; +UCHAR _ux_system_host_class_prolific_name[] = "ux_host_class_prolific"; +UCHAR _ux_system_host_class_pima_name[] = "ux_host_class_pima"; +UCHAR _ux_system_host_class_dpump_name[] = "ux_host_class_dpump"; +UCHAR _ux_system_host_class_asix_name[] = "ux_host_class_asix"; +UCHAR _ux_system_host_class_swar_name[] = "ux_host_class_sierra_wireless"; +UCHAR _ux_system_host_class_gser_name[] = "ux_host_class_generic_serial"; +UCHAR _ux_system_host_class_hid_client_remote_control_name[] = "ux_host_class_hid_client_remote_control"; +UCHAR _ux_system_host_class_hid_client_mouse_name[] = "ux_host_class_hid_client_mouse"; +UCHAR _ux_system_host_class_hid_client_keyboard_name[] = "ux_host_class_hid_client_keyboard"; + +/* Define the name of all the USB Host Controllers of USBX. */ + +UCHAR _ux_system_host_hcd_ohci_name[] = "ux_hcd_ohci"; +UCHAR _ux_system_host_hcd_ehci_name[] = "ux_hcd_ehci"; +UCHAR _ux_system_host_hcd_isp1161_name[] = "ux_hcd_isp1161"; +UCHAR _ux_system_host_hcd_isp1362_name[] = "ux_hcd_isp1362"; +UCHAR _ux_system_host_hcd_sh2_name[] = "ux_hcd_rx"; +UCHAR _ux_system_host_hcd_rx_name[] = "ux_hcd_sh2"; +UCHAR _ux_system_host_hcd_pic32_name[] = "ux_hcd_pic32"; +UCHAR _ux_system_host_hcd_stm32_name[] = "ux_hcd_stm32"; +UCHAR _ux_system_host_hcd_musb_name[] = "ux_hcd_musb"; +UCHAR _ux_system_host_hcd_atm7_name[] = "ux_hcd_atm7"; +UCHAR _ux_system_host_hcd_simulator_name[] = "ux_hcd_simulator"; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes all the host code for USBX to work on a */ +/* specific platform. */ +/* */ +/* INPUT */ +/* */ +/* (ux_system_host_change_function) Function pointer to the */ +/* callback function for a */ +/* device change */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate host memory */ +/* _ux_utility_semaphore_create Create host semaphore */ +/* _ux_utility_mutex_create Create host mutex */ +/* _ux_utility_thread_create Create host thread */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_initialize(UINT (*ux_system_host_change_function)(ULONG, UX_HOST_CLASS *, VOID *)) +{ + +UINT status; +UCHAR *memory; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_INITIALIZE, 0, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Initialize some of the global so that we don't have to recompile the + core code when one item is adjusted. */ + _ux_system_host -> ux_system_host_max_class = UX_MAX_CLASS_DRIVER; + _ux_system_host -> ux_system_host_max_hcd = UX_MAX_HCD; + _ux_system_host -> ux_system_host_max_devices = UX_MAX_DEVICES; + _ux_system_host -> ux_system_host_max_ed = UX_MAX_ED; + _ux_system_host -> ux_system_host_max_td = UX_MAX_TD; + _ux_system_host -> ux_system_host_max_iso_td = UX_MAX_ISO_TD; + + /* Set the change device function address. */ + _ux_system_host -> ux_system_host_change_function = ux_system_host_change_function; + + /* Allocate memory for the HCDs. + * sizeof(UX_HCD)*UX_MAX_HCD overflow is checked outside of the function. + */ + memory = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HCD)*UX_MAX_HCD); + + /* Check for successful allocation. */ + if (memory == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Set to success by default. */ + status = UX_SUCCESS; + + /* Store memory in system structure. */ + _ux_system_host -> ux_system_host_hcd_array = (UX_HCD *) memory; + + /* Allocate memory for the classes. + * sizeof(UX_HOST_CLASS)*UX_MAX_CLASS_DRIVER overflow is checked outside of the function. + */ + memory = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS)*UX_MAX_CLASS_DRIVER); + + /* Check for successful allocation. */ + if (memory == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + else + + /* Store memory in system structure. */ + _ux_system_host -> ux_system_host_class_array = (UX_HOST_CLASS *) memory; + + /* Allocate memory for the device containers. + * sizeof(UX_DEVICE)*UX_MAX_DEVICES overflow is checked outside of the function. + */ + if (status == UX_SUCCESS) + { + memory = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_DEVICE)*UX_MAX_DEVICES); + + /* Check for successful allocation. */ + if(memory == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + else + + /* Store memory in system structure. */ + _ux_system_host -> ux_system_host_device_array = (UX_DEVICE *) memory; + } + + /* Obtain enough stack for the two USBX host threads. */ + if (status == UX_SUCCESS) + { + _ux_system_host -> ux_system_host_enum_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, + UX_HOST_ENUM_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (_ux_system_host -> ux_system_host_enum_thread_stack == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Allocate another stack area. */ + if (status == UX_SUCCESS) + { + _ux_system_host -> ux_system_host_hcd_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, + UX_HOST_HCD_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (_ux_system_host -> ux_system_host_hcd_thread_stack == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Create the semaphores used by the hub and root hub to awake the enumeration thread. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&_ux_system_host -> ux_system_host_enum_semaphore, "ux_system_host_enum_semaphore", 0); + if(status != UX_SUCCESS) + status = UX_SEMAPHORE_ERROR; + } + + /* Create the semaphores used by the HCD to perform the completion phase of transfer_requests. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&_ux_system_host -> ux_system_host_hcd_semaphore, "ux_system_host_hcd_semaphore", 0); + if(status != UX_SUCCESS) + status = UX_SEMAPHORE_ERROR; + } + + /* Create the enumeration thread of USBX. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_thread_create(&_ux_system_host -> ux_system_host_enum_thread, "ux_system_host_enum_thread", _ux_host_stack_enum_thread_entry, + 0, _ux_system_host -> ux_system_host_enum_thread_stack, + UX_HOST_ENUM_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_ENUM, + UX_THREAD_PRIORITY_ENUM, UX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check the completion status. */ + if(status != UX_SUCCESS) + status = UX_THREAD_ERROR; + } + + /* Create the HCD thread of USBX. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_thread_create(&_ux_system_host -> ux_system_host_hcd_thread, "ux_host_stack_hcd_thread", _ux_host_stack_hcd_thread_entry, + 0, _ux_system_host -> ux_system_host_hcd_thread_stack, + UX_HOST_HCD_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_HCD, + UX_THREAD_PRIORITY_HCD, UX_NO_TIME_SLICE,TX_AUTO_START); + + /* Check the completion status. */ + if(status != UX_SUCCESS) + status = UX_THREAD_ERROR; + } + +#ifdef UX_OTG_SUPPORT + /* Allocate another stack area for the HNP polling thread. */ + if (status == UX_SUCCESS) + { + _ux_system_host -> ux_system_host_hnp_polling_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, + UX_HOST_HNP_POLLING_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (_ux_system_host -> ux_system_host_hnp_polling_thread_stack == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Create the HNP polling thread of USBX. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_thread_create(&_ux_system_host -> ux_system_host_hnp_polling_thread, "ux_host_stack_hnp_polling_thread", _ux_host_stack_hnp_polling_thread_entry, + 0, _ux_system_host -> ux_system_host_hnp_polling_thread_stack, + UX_HOST_HNP_POLLING_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_ENUM, + UX_THREAD_PRIORITY_ENUM, UX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check the completion status. */ + if (status != UX_SUCCESS) + status = UX_THREAD_ERROR; + + /* Return success (SUCCESS). */ + else + return(status); + } + + /* Free up resources on error cases. */ + + /* Last resource, _ux_system_host -> ux_system_host_hnp_polling_thread is not created or created error, + * no need to delete it. */ + + /* Free _ux_system_host -> ux_system_host_hnp_polling_thread_stack. */ + if (_ux_system_host -> ux_system_host_hnp_polling_thread_stack) + _ux_utility_memory_free(_ux_system_host -> ux_system_host_hnp_polling_thread_stack); + + /* Delete _ux_system_host -> ux_system_host_hcd_thread. */ + if (_ux_system_host -> ux_system_host_hcd_thread.tx_thread_id != 0) + _ux_utility_thread_delete(&_ux_system_host -> ux_system_host_hcd_thread); +#else + + /* Return completion status to caller if success. */ + if (status == UX_SUCCESS) + return(status); + + /* Free up resources on error cases. */ + + /* Last resource, _ux_system_host -> ux_system_host_hcd_thread is not created or created error, + * no need to delete it. */ +#endif + + /* Delete _ux_system_host -> ux_system_host_enum_thread. */ + if (_ux_system_host -> ux_system_host_enum_thread.tx_thread_id != 0) + _ux_utility_thread_delete(&_ux_system_host -> ux_system_host_enum_thread); + + /* Delete _ux_system_host -> ux_system_host_hcd_semaphore. */ + if (_ux_system_host -> ux_system_host_hcd_semaphore.tx_semaphore_id != 0) + _ux_utility_semaphore_delete(&_ux_system_host -> ux_system_host_hcd_semaphore); + + /* Delete _ux_system_host -> ux_system_host_enum_semaphore. */ + if (_ux_system_host -> ux_system_host_enum_semaphore.tx_semaphore_id != 0) + _ux_utility_semaphore_delete(&_ux_system_host -> ux_system_host_enum_semaphore); + + /* Free _ux_system_host -> ux_system_host_hcd_thread_stack. */ + if (_ux_system_host -> ux_system_host_hcd_thread_stack) + _ux_utility_memory_free(_ux_system_host -> ux_system_host_hcd_thread_stack); + + /* Free _ux_system_host -> ux_system_host_enum_thread_stack. */ + if (_ux_system_host -> ux_system_host_enum_thread_stack) + _ux_utility_memory_free(_ux_system_host -> ux_system_host_enum_thread_stack); + + /* Free _ux_system_host -> ux_system_host_device_array. */ + if (_ux_system_host -> ux_system_host_device_array) + _ux_utility_memory_free(_ux_system_host -> ux_system_host_device_array); + + /* Free _ux_system_host -> ux_system_host_class_array. */ + if (_ux_system_host -> ux_system_host_class_array) + _ux_utility_memory_free(_ux_system_host -> ux_system_host_class_array); + + /* Free _ux_system_host -> ux_system_host_hcd_array. */ + _ux_utility_memory_free(_ux_system_host -> ux_system_host_hcd_array); + + /* Return completion status to caller. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_interface_endpoint_get.c b/common/core/src/ux_host_stack_interface_endpoint_get.c new file mode 100644 index 0000000..549b79b --- /dev/null +++ b/common/core/src/ux_host_stack_interface_endpoint_get.c @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_interface_endpoint_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns an endpoint container based on the interface */ +/* handle and an endpoint index. */ +/* */ +/* INPUT */ +/* */ +/* interface Pointer to interface */ +/* endpoint_index Index of endpoint to get */ +/* endpoint Destination for endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_interface_endpoint_get(UX_INTERFACE *interface, UINT endpoint_index, UX_ENDPOINT **endpoint) +{ + +UINT current_endpoint_index; +UX_ENDPOINT *current_endpoint; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_INTERFACE_ENDPOINT_GET, interface, endpoint_index, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Do a sanity check on the interface handle. */ + if (interface -> ux_interface_handle != (ULONG) (ALIGN_TYPE) interface) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_INTERFACE_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_INTERFACE_HANDLE_UNKNOWN, interface, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_INTERFACE_HANDLE_UNKNOWN); + } + + /* Start with the endpoint attached to the interface. */ + current_endpoint = interface -> ux_interface_first_endpoint; + + /* The first endpoint has the index 0. */ + current_endpoint_index = 0; + + /* Traverse the list of the endpoints until we found the right one. */ + while (current_endpoint != UX_NULL) + { + + /* Check if the endpoint index matches the current one. */ + if (endpoint_index == current_endpoint_index) + { + + /* Setup the return endpoint pointer. */ + *endpoint=current_endpoint; + + /* Return success to the caller. */ + return(UX_SUCCESS); + } + + /* Move to the next endpoint. */ + current_endpoint = current_endpoint -> ux_endpoint_next_endpoint; + + /* Move to the next index. */ + current_endpoint_index++; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error! */ + return(UX_ENDPOINT_HANDLE_UNKNOWN); +} + diff --git a/common/core/src/ux_host_stack_interface_instance_create.c b/common/core/src/ux_host_stack_interface_instance_create.c new file mode 100644 index 0000000..79482fc --- /dev/null +++ b/common/core/src/ux_host_stack_interface_instance_create.c @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_interface_instance_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will create an interface instance. It creates each */ +/* endpoint associated with the interface. */ +/* */ +/* INPUT */ +/* */ +/* interface Pointer to interface */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_endpoint_instance_create Create instance endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_interface_instance_create(UX_INTERFACE *interface) +{ + +UX_ENDPOINT *endpoint; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_INTERFACE_INSTANCE_CREATE, interface, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Obtain the first endpoint for this alternate setting. */ + endpoint = interface -> ux_interface_first_endpoint; + + /* Loop to create each endpoint. */ + while (endpoint != UX_NULL) + { + + /* Create an endpoint for the instance. */ + status = _ux_host_stack_endpoint_instance_create(endpoint); + + /* Check status, the controller may have refused the endpoint creation. */ + if (status != UX_SUCCESS) + + /* An error occurred at the controller level. */ + return(status); + + /* Move to next endpoint. */ + endpoint = endpoint -> ux_endpoint_next_endpoint; + } + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, interface, 0, 0, 0); + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_interface_instance_delete.c b/common/core/src/ux_host_stack_interface_instance_delete.c new file mode 100644 index 0000000..f12b1f5 --- /dev/null +++ b/common/core/src/ux_host_stack_interface_instance_delete.c @@ -0,0 +1,99 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_interface_instance_delete PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will delete an interface instance. It does not delete */ +/* the interface container, but it removes all the endpoints */ +/* associated with alternate setting. */ +/* */ +/* INPUT */ +/* */ +/* interface Pointer to interface */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_endpoint_instance_delete Delete endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_stack_interface_instance_delete(UX_INTERFACE *interface) +{ + +UX_ENDPOINT *endpoint; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_INTERFACE_INSTANCE_DELETE, interface, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(interface); + + /* Obtain the first endpoint for this alternate setting. */ + endpoint = interface -> ux_interface_first_endpoint; + + /* Loop to delete each endpoint. */ + while (endpoint != UX_NULL) + { + + /* Delete endpoint. */ + _ux_host_stack_endpoint_instance_delete(endpoint); + + /* Move to next endpoint. */ + endpoint = endpoint -> ux_endpoint_next_endpoint; + } + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_host_stack_interface_set.c b/common/core/src/ux_host_stack_interface_set.c new file mode 100644 index 0000000..dd62866 --- /dev/null +++ b/common/core/src/ux_host_stack_interface_set.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_interface_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a setting of an alternate setting for a */ +/* specific interface. */ +/* */ +/* INPUT */ +/* */ +/* interface Pointer to interface */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_hcd_transfer_request HCD transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_interface_set(UX_INTERFACE *interface) +{ + +UX_DEVICE *device; +UX_CONFIGURATION *configuration; +UX_TRANSFER *transfer_request; +UINT status; +UX_ENDPOINT *control_endpoint; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_INTERFACE_SET, interface, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Retrieve the pointer to the control endpoint and its transfer_request. + From the interface we go back to the configuration, then the device. + The device contains the default control endpoint container. */ + configuration = interface -> ux_interface_configuration; + device = configuration -> ux_configuration_device; + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Create a transfer_request for the SET_INTERFACE request. No data for this request */ + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_SET_INTERFACE; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_index = (USHORT) interface -> ux_interface_descriptor.bInterfaceNumber; + transfer_request -> ux_transfer_request_value = (USHORT) interface -> ux_interface_descriptor.bAlternateSetting; + + /* Send request to HCD layer. */ + status = _ux_host_stack_hcd_transfer_request(transfer_request); + + /* Return status completion. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_interface_setting_select.c b/common/core/src/ux_host_stack_interface_setting_select.c new file mode 100644 index 0000000..5fb24a7 --- /dev/null +++ b/common/core/src/ux_host_stack_interface_setting_select.c @@ -0,0 +1,203 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_interface_setting_select PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function selects a specific alternate setting for a given */ +/* interface belonging to the selected configuration. */ +/* */ +/* INPUT */ +/* */ +/* interface Pointer to interface */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_instance_create Create interface instance */ +/* _ux_host_stack_interface_instance_delete Delete interface instance */ +/* _ux_host_stack_interface_set Set interface instance */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_interface_setting_select(UX_INTERFACE *interface) +{ + +UX_CONFIGURATION *configuration; +UX_INTERFACE *current_interface; +UX_INTERFACE *previous_interface; +UX_INTERFACE *main_interface; +UINT current_interface_number; +UINT current_alternate_setting; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_INTERFACE_SETTING_SELECT, interface, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Check this alternate setting container. It must be valid before + we continue. */ + if (interface -> ux_interface_handle != (ULONG) (ALIGN_TYPE) interface) + { + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_INTERFACE_HANDLE_UNKNOWN, interface, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_INTERFACE_HANDLE_UNKNOWN); + } + + /* From the interface, get the configuration container and the first + interface hooked to this configuration. */ + configuration = interface -> ux_interface_configuration; + current_interface_number = interface -> ux_interface_descriptor.bInterfaceNumber; + current_interface = configuration -> ux_configuration_first_interface; + + /* Remember the main interface to store the next alternate setting. We set the main interface + to the first interface to keep the compiler happy. */ + main_interface = current_interface; + + /* In order to keep the compiler happy, we reset the alternate setting. */ + current_alternate_setting = 0; + previous_interface = UX_NULL; + + /* Search for the current alternate setting for this interface. + All its endpoints will need to be destroyed. + Since interfaces in the parent configuration should be linked together + in correct way, just find it in while loop. + */ + while (1) + { + + /* Try to locate the first interface container in the interface chain which + has the same interface number as the one supplied by the caller. */ + if (current_interface -> ux_interface_descriptor.bInterfaceNumber == current_interface_number) + { + + /* The alternate setting 0 of this interface has the current selected + alternate setting. */ + if (current_interface -> ux_interface_descriptor.bAlternateSetting == 0) + { + + /* Set the alternate setting. */ + current_alternate_setting = current_interface -> ux_interface_current_alternate_setting; + + /* Remember the main interface to store the next alternate setting. */ + main_interface = current_interface; + + } + + /* See if the current alternate setting matches that of the interface alternate setting. */ + if (current_alternate_setting == current_interface -> ux_interface_descriptor.bAlternateSetting) + { + + /* Yes, save the current alternate setting. */ + previous_interface = current_interface; + + /* Then delete the current interface. */ + _ux_host_stack_interface_instance_delete(current_interface); + + /* We are done in this loop. */ + break; + + } + } + + /* Move to the next interface. */ + current_interface = current_interface -> ux_interface_next_interface; + } + + /* Remember the new alternate setting. */ + main_interface -> ux_interface_current_alternate_setting = interface -> ux_interface_descriptor.bAlternateSetting; + + /* Now, the interface must be created with the new alternate setting. */ + status = _ux_host_stack_interface_instance_create(interface); + + /* If we could not create it, we return to the default one. */ + if (status != UX_SUCCESS) + { + + /* Then delete the failed interface. */ + _ux_host_stack_interface_instance_delete(interface); + + /* Error, reset the main interface alternate setting to the default. */ + main_interface -> ux_interface_current_alternate_setting = current_alternate_setting; + + /* Re-create the previous interface with the old alternate setting. */ + _ux_host_stack_interface_instance_create(previous_interface); + + /* Return error status. */ + return(status); + } + + /* Issue a SET_INTERFACE command to the target device. */ + status = _ux_host_stack_interface_set(interface); + + /* Check completion status. */ + if (status != UX_SUCCESS) + { + + /* Error, reset the main interface alternate setting to the default. */ + main_interface -> ux_interface_current_alternate_setting = current_alternate_setting; + + /* Delete the current interface. */ + _ux_host_stack_interface_instance_delete(interface); + + /* Re-create the previous interface with the old alternate setting. */ + _ux_host_stack_interface_instance_create(previous_interface); + + /* Return error status. */ + return(status); + } + + /* Return to caller. */ + return(status); +} + diff --git a/common/core/src/ux_host_stack_interfaces_scan.c b/common/core/src/ux_host_stack_interfaces_scan.c new file mode 100644 index 0000000..41cf9cd --- /dev/null +++ b/common/core/src/ux_host_stack_interfaces_scan.c @@ -0,0 +1,201 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_interfaces_scan PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function scans all the interfaces and alternate settings for */ +/* particular configuration. */ +/* */ +/* INPUT */ +/* */ +/* configuration Where the interface(s) will */ +/* be attached */ +/* descriptor Contains the entire descriptor*/ +/* for this configuration */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_descriptor_parse Parse interface descriptor */ +/* _ux_host_stack_new_interface_create Create new interface */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_interfaces_scan(UX_CONFIGURATION *configuration, UCHAR * descriptor) +{ + +ULONG total_configuration_length; +UINT descriptor_length; +UINT descriptor_type; +ULONG status; +ULONG interface_association_descriptor_present; +ULONG interface_in_iad_count; +UX_INTERFACE_ASSOCIATION_DESCRIPTOR interface_association; + + /* Retrieve the size of all the configuration descriptor. */ + total_configuration_length = configuration -> ux_configuration_descriptor.wTotalLength; + + /* Set the IAD to false. */ + interface_association_descriptor_present = UX_FALSE; + + /* Set the IAD interface count to zero. */ + interface_in_iad_count = 0; + + /* Scan the entire descriptor and search for interfaces. We should also ensure that + the descriptor is valid by verifying the length of each descriptor scanned. */ + while (total_configuration_length) + { + + /* Gather the length and type of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Check the type for an interface association descriptor. */ + if (descriptor_type == UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ITEM) + { + + /* Parse the interface association descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, + _ux_system_interface_association_descriptor_structure, + UX_INTERFACE_ASSOCIATION_DESCRIPTOR_ENTRIES, + (UCHAR *) &interface_association); + + /* Retrieve the CLASS/SUBCLASS from descriptor and store it in the configuration instance. */ + configuration -> ux_configuration_iad_class = interface_association.bFunctionClass; + configuration -> ux_configuration_iad_subclass = interface_association.bFunctionSubClass; + configuration -> ux_configuration_iad_protocol = interface_association.bFunctionProtocol; + + /* We have an IAD. */ + interface_association_descriptor_present = UX_TRUE; + + /* Memorize the number of interfaces attached to this IAD. */ + interface_in_iad_count = interface_association.bInterfaceCount; + } + + /* Check the type for an interface descriptor. */ + if (descriptor_type == UX_INTERFACE_DESCRIPTOR_ITEM) + { + + /* We have found an interface descriptor. This descriptor contains at least + the default alternate setting (with value 0) and may have others. */ + status = _ux_host_stack_new_interface_create(configuration, descriptor, total_configuration_length); + + /* Are we within an IAD ? */ + if (interface_association_descriptor_present == UX_TRUE) + { + + /* Decrement the number of interfaces attached here. */ + interface_in_iad_count--; + + /* Are we at the end of the interface count ? */ + if (interface_in_iad_count == 0) + { + + /* Set the IAD to false now. */ + interface_association_descriptor_present = UX_FALSE; + + /* Reset the IAD Class/Subclass/Protocol. */ + configuration -> ux_configuration_iad_class = 0; + configuration -> ux_configuration_iad_subclass = 0; + configuration -> ux_configuration_iad_protocol = 0; + + } + } + + /* Check return status. */ + if(status != UX_SUCCESS) + return(status); + } + + /* Check the type for an OTG descriptor. */ + if (descriptor_type == UX_OTG_DESCRIPTOR_ITEM) + + /* Retrieve the bmAttributes for SRP/HNP support. */ + configuration -> ux_configuration_otg_capabilities = (ULONG) *(descriptor + UX_OTG_BM_ATTRIBUTES); + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_configuration_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_configuration_length -= descriptor_length; + } + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_new_configuration_create.c b/common/core/src/ux_host_stack_new_configuration_create.c new file mode 100644 index 0000000..e982289 --- /dev/null +++ b/common/core/src/ux_host_stack_new_configuration_create.c @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_new_configuration_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a new configuration for the current device */ +/* a device can have multiple configurations. */ +/* */ +/* INPUT */ +/* */ +/* device Pointer to the descriptor */ +/* for the device */ +/* configuration_descriptor Configuration descriptor */ +/* previously parsed */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_stack_new_configuration_create(UX_DEVICE *device, UX_CONFIGURATION *configuration) +{ + +UX_CONFIGURATION *list_configuration; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_NEW_CONFIGURATION_CREATE, device, configuration, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* The device that owns this configuration is memorized in the + configuration container itself, easier for back chaining. */ + configuration -> ux_configuration_device = device; + + /* Save the configuration handle in the container, this is for ensuring the + configuration container is not corrupted. */ + configuration -> ux_configuration_handle = (ULONG) (ALIGN_TYPE) configuration; + + /* There is 2 cases for the creation of the configuration descriptor + if this is the first one, the configuration descriptor is hooked + to the device. If it is not the first one, the configuration is + hooked to the end of the chain of configurations. */ + if (device -> ux_device_first_configuration == UX_NULL) + { + device -> ux_device_first_configuration = configuration; + } + else + { + + /* Get the pointer to the first configuration. */ + list_configuration = device -> ux_device_first_configuration; + + /* And traverse until we have reached the end of the configuration list. */ + while (list_configuration -> ux_configuration_next_configuration != UX_NULL) + { + list_configuration = list_configuration -> ux_configuration_next_configuration; + } + + /* Hook the new configuration. */ + list_configuration -> ux_configuration_next_configuration = configuration; + } + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_host_stack_new_device_create.c b/common/core/src/ux_host_stack_new_device_create.c new file mode 100644 index 0000000..387cba9 --- /dev/null +++ b/common/core/src/ux_host_stack_new_device_create.c @@ -0,0 +1,244 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_new_device_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a new device on the USB. It may be called */ +/* either by a hub or by the root hub. */ +/* */ +/* INPUT */ +/* */ +/* HCD HCD that owns that device */ +/* device_owner Either a root hub instance */ +/* or a hub instance */ +/* port_index Port the new device is mounted*/ +/* device_speed Speed at which the device is */ +/* running (low, full, high) */ +/* port_power_available Power available on the root */ +/* or hub port. This value is */ +/* used to ensure that the */ +/* device can be configured */ +/* without creating an */ +/* OVER_CURRENT condition on */ +/* the bus */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* An Error code could be an indication that the device could not be */ +/* created in which case the error is fatal to the enumeration and */ +/* will not be retried. The error code can also indicate a failure */ +/* for the device to respond to the GET_DEVICE_DESCRIPTOR. This error */ +/* is not fatal and the caller should retry the enumeration process */ +/* after the port to which the device is attached has been reset. */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_device_scan Scan class devices */ +/* _ux_host_stack_class_interface_scan Scan class interfaces */ +/* _ux_host_stack_device_address_set Set device address */ +/* _ux_host_stack_device_descriptor_read Read device descriptor */ +/* _ux_host_stack_configuration_enumerate */ +/* Enumerate device config */ +/* _ux_host_stack_new_device_get Get new device */ +/* _ux_utility_semaphore_create Create a semaphore */ +/* (ux_hcd_entry_function) HCD entry function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_new_device_create(UX_HCD *hcd, UX_DEVICE *device_owner, + UINT port_index, UINT device_speed, + UINT port_max_power) +{ + +UX_DEVICE *device; +UINT status; +UX_ENDPOINT *control_endpoint; + + + /* Verify the number of devices attached to the HCD already. Normally a HCD + can have up to 127 devices but that can be tailored. */ + if (hcd -> ux_hcd_nb_devices > UX_MAX_USB_DEVICES) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_TOO_MANY_DEVICES); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TOO_MANY_DEVICES, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_TOO_MANY_DEVICES); + } + + /* Get a new device container to store this new device. */ + device = _ux_host_stack_new_device_get(); + if (device == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_TOO_MANY_DEVICES); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TOO_MANY_DEVICES, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_TOO_MANY_DEVICES); + } + + /* Increment the number of devices on this bus. */ + hcd -> ux_hcd_nb_devices++; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_NEW_DEVICE_CREATE, hcd, device_owner, port_index, device, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* At this stage the device is attached but not configured. + we don't have to worry about power consumption yet. + Initialize the device structure. */ + device -> ux_device_handle = (ULONG) (ALIGN_TYPE) device; + device -> ux_device_state = UX_DEVICE_ATTACHED; + device -> ux_device_parent = device_owner; + device -> ux_device_hcd = hcd; + device -> ux_device_speed = device_speed; + device -> ux_device_port_location = port_index; + device -> ux_device_max_power = port_max_power; + + /* Create a semaphore for the device. This is to protect endpoint 0 mostly for OTG HNP polling. The initial count is 1 as + a mutex mechanism. */ + status = _ux_utility_semaphore_create(&device -> ux_device_protection_semaphore, "ux_host_endpoint0_semaphore", 1); + + /* Check semaphore creation. */ + if (status != UX_SUCCESS) + { + + /* Return error. Device resources that have been allocated until this + point should be freed by the caller via _ux_host_stack_device_resources_free. */ + return(UX_SEMAPHORE_ERROR); + } + + /* Initialize the default control endpoint permanently attached + to the device. */ + control_endpoint = &device -> ux_device_control_endpoint; + control_endpoint -> ux_endpoint = (ULONG) (ALIGN_TYPE) control_endpoint; + control_endpoint -> ux_endpoint_next_endpoint = UX_NULL; + control_endpoint -> ux_endpoint_interface = UX_NULL; + control_endpoint -> ux_endpoint_device = device; + control_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_endpoint = control_endpoint; + + /* Create a semaphore for this endpoint to be attached to its transfer request. */ + status = _ux_utility_semaphore_create(&control_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_semaphore, "ux_host_transfer_request_semaphore", 0); + + /* Check semaphore creation. */ + if (status != UX_SUCCESS) + { + + /* Return error. Device resources that have been allocated until this + point should be freed by the caller via _ux_host_stack_device_resources_free. */ + return(UX_SEMAPHORE_ERROR); + } + + /* If the device is running in high speed the default max packet size for the control endpoint is 64. + All other speeds the size is 8. */ + if (device_speed == UX_HIGH_SPEED_DEVICE) + control_endpoint -> ux_endpoint_descriptor.wMaxPacketSize = UX_DEFAULT_HS_MPS; + else + control_endpoint -> ux_endpoint_descriptor.wMaxPacketSize = UX_DEFAULT_MPS; + + /* Create the default control endpoint at the HCD level. */ + status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_CREATE_ENDPOINT, (VOID *) control_endpoint); + if (status == UX_SUCCESS) + { + + /* Now control endpoint is ready, set state to running. */ + control_endpoint -> ux_endpoint_state = UX_ENDPOINT_RUNNING; + + /* Set the address of the device. The first time a USB device is + accessed, it responds to the address 0. We need to change the address + to a free device address between 1 and 127 ASAP. */ + status = _ux_host_stack_device_address_set(device); + if (status == UX_SUCCESS) + { + + /* Get the device descriptor. */ + status = _ux_host_stack_device_descriptor_read(device); + if (status == UX_SUCCESS) + { + + /* Get the configuration descriptor(s) for the device + and parse all the configuration, interface, endpoints... */ + status = _ux_host_stack_configuration_enumerate(device); + } + } + } + + /* Check the status of the previous operations. If there was an + error during any of the phases, the device resources must be + freed based on if we want to retry. */ + if (status == UX_SUCCESS) + { + + /* The device, configuration(s), interface(s), endpoint(s) are + now in order for this device to work. No configuration is set + yet. First we need to find a class driver that wants to own + it. There is no need to have an orphan device in a configured state. */ + status = _ux_host_stack_class_device_scan(device); + if (status == UX_NO_CLASS_MATCH) + { + + status = _ux_host_stack_class_interface_scan(device); + } + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_DEVICE, hcd, device_owner, port_index, 0); + } + + /* Return status. If there's an error, device resources that have been + allocated until this point should be freed by the caller via _ux_host_stack_device_resources_free. */ + return(status); +} diff --git a/common/core/src/ux_host_stack_new_device_get.c b/common/core/src/ux_host_stack_new_device_get.c new file mode 100644 index 0000000..88fbb2f --- /dev/null +++ b/common/core/src/ux_host_stack_new_device_get.c @@ -0,0 +1,107 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_new_device_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains a free device container for the new device. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* UX_DEVICE pointer */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_set Set memory to a value */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_DEVICE *_ux_host_stack_new_device_get(VOID) +{ + +ULONG container_index; +UX_DEVICE *device; + + + /* Start with the first device. */ + device = _ux_system_host -> ux_system_host_device_array; + + /* Reset the container index. */ + container_index = 0; + + /* Search the list until the end. */ + while (container_index++ < _ux_system_host -> ux_system_host_max_devices) + { + + /* Until we have found an unused entry. */ + if (device -> ux_device_handle == UX_UNUSED) + { + + /* Reset the entire entry. */ + _ux_utility_memory_set(device, 0, sizeof(UX_DEVICE)); + + /* This entry is now used. */ + device -> ux_device_handle = UX_USED; + + /* Return the device pointer. */ + return(device); + } + + /* Move to the next device entry. */ + device++; + } + + /* No unused devices, return NULL. */ + return(UX_NULL); +} + diff --git a/common/core/src/ux_host_stack_new_endpoint_create.c b/common/core/src/ux_host_stack_new_endpoint_create.c new file mode 100644 index 0000000..abadc00 --- /dev/null +++ b/common/core/src/ux_host_stack_new_endpoint_create.c @@ -0,0 +1,139 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_new_endpoint_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a new endpoint for the current interface */ +/* scanned. The endpoint is hooked to the interface that owns it. */ +/* It is not active yet until either the default interface for the */ +/* configuration is selected by a SET_CONFIGURATION or when an */ +/* alternate setting for this interface is set. */ +/* */ +/* INPUT */ +/* */ +/* interface Interface container that owns */ +/* this endpoint */ +/* endpoint_pointer Pointer to a unparsed */ +/* endpoint descriptor */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_descriptor_parse Parse the descriptor */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_new_endpoint_create(UX_INTERFACE *interface, + UCHAR * interface_endpoint) +{ + +UX_ENDPOINT *endpoint; +UX_ENDPOINT *list_endpoint; + + /* Obtain memory for storing this new endpoint. */ + endpoint = (UX_ENDPOINT *) _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_ENDPOINT)); + if (endpoint == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_NEW_ENDPOINT_CREATE, interface, endpoint, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Save the endpoint handle in the container, this is for ensuring the + endpoint container is not corrupted. */ + endpoint -> ux_endpoint = (ULONG) (ALIGN_TYPE) endpoint; + + /* The endpoint container has a built in transfer_request. + The transfer_request needs to point to the endpoint as well. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_endpoint = endpoint; + + /* Save the pointer to the device. This is useful for the HCD layer. */ + endpoint -> ux_endpoint_device = interface -> ux_interface_configuration -> ux_configuration_device; + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(interface_endpoint, + _ux_system_endpoint_descriptor_structure, + UX_ENDPOINT_DESCRIPTOR_ENTRIES, + (UCHAR *) &endpoint -> ux_endpoint_descriptor); + + /* The interface that owns this endpoint is memorized in the + endpoint container itself, easier for back chaining. */ + endpoint -> ux_endpoint_interface = interface; + + /* There is 2 cases for the creation of the endpoint descriptor + if this is the first one, the endpoint descriptor is hooked + to the interface. + If it is not the first one, the endpoint is hooked to the + end of the chain of endpoints. */ + if (interface -> ux_interface_first_endpoint == UX_NULL) + { + + interface -> ux_interface_first_endpoint = endpoint; + } + else + { + + list_endpoint = interface -> ux_interface_first_endpoint; + + /* Traverse the list until the end. */ + while (list_endpoint -> ux_endpoint_next_endpoint != UX_NULL) + list_endpoint = list_endpoint -> ux_endpoint_next_endpoint; + + /* Hook the endpoint. */ + list_endpoint -> ux_endpoint_next_endpoint = endpoint; + } + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_new_interface_create.c b/common/core/src/ux_host_stack_new_interface_create.c new file mode 100644 index 0000000..14c9c5a --- /dev/null +++ b/common/core/src/ux_host_stack_new_interface_create.c @@ -0,0 +1,207 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_new_interface_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a new interface for the current configuration */ +/* scanned. A device has at least 1 alternate setting per interface */ +/* which is the default one. */ +/* */ +/* The interface is hooked to the configuration that owns it. */ +/* */ +/* From the interface descriptor, all the endpoints are hooked but */ +/* not activated. */ +/* */ +/* INPUT */ +/* */ +/* configuration Configuration container that */ +/* owns this interface */ +/* interface_pointer Pointer to a unparsed */ +/* interface descriptor */ +/* length Length remaining in this */ +/* descriptor */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_new_endpoint_create Create new endpoint */ +/* _ux_utility_descriptor_parse Parse the descriptor */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_new_interface_create(UX_CONFIGURATION *configuration, + UCHAR * descriptor, ULONG length) +{ + +UX_INTERFACE *list_interface; +UX_INTERFACE *interface; +UINT number_endpoints; +UINT descriptor_length; +UINT descriptor_type; +UINT status; +UCHAR *this_interface_descriptor; + + /* Obtain memory for storing this new interface. */ + interface = (UX_INTERFACE *) _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_INTERFACE)); + + /* If no memory left, exit with error. */ + if (interface == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save the interface handle in the container, this is for ensuring the + interface container is not corrupted. */ + interface -> ux_interface_handle = (ULONG) (ALIGN_TYPE) interface; + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, + _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, + (UCHAR *) &interface -> ux_interface_descriptor); + + /* The configuration that owns this interface is memorized in the + interface container itself, easier for back chaining. */ + interface -> ux_interface_configuration = configuration; + + /* If the interface belongs to an IAD, remember the IAD Class/SubClass/Protocol. */ + interface -> ux_interface_iad_class = configuration -> ux_configuration_iad_class; + interface -> ux_interface_iad_subclass = configuration -> ux_configuration_iad_subclass; + interface -> ux_interface_iad_protocol = configuration -> ux_configuration_iad_protocol; + + /* There is 2 cases for the creation of the interface descriptor + if this is the first one, the interface descriptor is hooked + to the configuration. If it is not the first one, the interface + is hooked to the end of the chain of interfaces. */ + if (configuration -> ux_configuration_first_interface == UX_NULL) + { + configuration -> ux_configuration_first_interface = interface; + } + else + { + + list_interface = configuration -> ux_configuration_first_interface; + + /* Traverse the list until we reach the end */ + while (list_interface -> ux_interface_next_interface != UX_NULL) + { + + list_interface = list_interface -> ux_interface_next_interface; + } + + /* Hook the interface. */ + list_interface -> ux_interface_next_interface = interface; + } + + /* Traverse the interface in search of all endpoints that belong to it. + We need the length remaining in the descriptor and the number of endpoints + reported for this interface. */ + number_endpoints = interface -> ux_interface_descriptor.bNumEndpoints; + + this_interface_descriptor = descriptor; + + while (length && (number_endpoints != 0)) + { + + /* Gather the length and type of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor+1); + + /* make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Check the type for an interface descriptor. */ + if (descriptor_type == UX_ENDPOINT_DESCRIPTOR_ITEM) + { + + /* We have found an endpoint descriptor for this interface. */ + status = _ux_host_stack_new_endpoint_create(interface, descriptor); + + /* Check return status. */ + if(status != UX_SUCCESS) + return(status); + + number_endpoints--; + } + + /* Verify if the descriptor is still valid, or we moved to next interface. */ + if ((descriptor_length > length) || (descriptor_type == UX_INTERFACE_DESCRIPTOR_ITEM && descriptor != this_interface_descriptor)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + length -= descriptor_length; + } + + /* Return success! */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_rh_change_process.c b/common/core/src/ux_host_stack_rh_change_process.c new file mode 100644 index 0000000..91bc167 --- /dev/null +++ b/common/core/src/ux_host_stack_rh_change_process.c @@ -0,0 +1,173 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_rh_change_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for changes in topology in each of the */ +/* installed HCDs. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_rh_device_insertion Process device insertion */ +/* _ux_host_stack_rh_device_extraction Process device extraction */ +/* (ux_hcd_entry_function) HCD entry function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_stack_rh_change_process(VOID) +{ + +UX_HCD *hcd; +UINT hcd_index; +ULONG port_status; +UINT port_index; +UX_INT_SAVE_AREA + + /* This thread was maybe awaken by one or more HCD controllers. Check each + of the HCD to see where there has been a change of topology. */ + for(hcd_index = 0; hcd_index < _ux_system_host -> ux_system_host_registered_hcd; hcd_index++) + { + + /* Pickup HCD pointer. */ + hcd = &_ux_system_host -> ux_system_host_hcd_array[hcd_index]; + + /* Is this HCD operational? */ + if (hcd -> ux_hcd_status == UX_HCD_STATUS_OPERATIONAL) + { + + /* On each port of the root hub of the controller, get the port status */ + for (port_index = 0; port_index < hcd -> ux_hcd_nb_root_hubs; port_index++) + { + + /* Was there any activity on this port ? */ + if (hcd -> ux_hcd_root_hub_signal[port_index] != 0) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_RH_CHANGE_PROCESS, port_index, 0, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Reset that port activity signal. */ + UX_DISABLE_INTS + hcd -> ux_hcd_root_hub_signal[port_index]--; + UX_RESTORE_INTS + + /* Call HCD for port status. */ + port_status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_GET_PORT_STATUS, (VOID *)((ALIGN_TYPE)port_index)); + + /* Check return status. */ + if (port_status != UX_PORT_INDEX_UNKNOWN) + { + + /* The port_status value is valid and will tell us if there is + a device attached\detached on the downstream port. */ + if (port_status & UX_PS_CCS) + { + + /* There is a device attached to this port. Check if we know + about it. If not, this is a device insertion signal. */ + if ((hcd -> ux_hcd_rh_device_connection & (ULONG)(1 << port_index)) == 0) + { + + /* We have a simple device insertion, we have not lost any signals. + the root hub and the stack enumeration module are in synch. */ + _ux_host_stack_rh_device_insertion(hcd,port_index); + } + else + { + /* We can get here when there has been multiple events on the hardware root hub + but we may have missed them of they were too close or the stack got too busy. + We check the number of events in the root hub signal. If it is not zero + we are out of synch, meaning we got a disconnection followed very quickly + by a insertion. */ + + if (hcd -> ux_hcd_root_hub_signal[port_index] != 0) + { + + /* We need to get back in synch now. */ + UX_DISABLE_INTS + hcd -> ux_hcd_root_hub_signal[port_index] = 0; + UX_RESTORE_INTS + + /* First extract the device. */ + _ux_host_stack_rh_device_extraction(hcd,port_index); + + /* Now, insert it again. */ + _ux_host_stack_rh_device_insertion(hcd,port_index); + + + } + + } + } + else + { + + /* There is no device attached to this port. Check if we know + about it. If not, this is a device removal signal. */ + if ((hcd -> ux_hcd_rh_device_connection & (ULONG)(1 << port_index)) !=0) + { + _ux_host_stack_rh_device_extraction(hcd,port_index); + } + } + } + } + } + } + } +} + diff --git a/common/core/src/ux_host_stack_rh_device_extraction.c b/common/core/src/ux_host_stack_rh_device_extraction.c new file mode 100644 index 0000000..90d8b80 --- /dev/null +++ b/common/core/src/ux_host_stack_rh_device_extraction.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_rh_device_extraction PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles a device extraction on a downstream port */ +/* of the root hub pointed by HCD. */ +/* */ +/* INPUT */ +/* */ +/* HCD Pointer to HCD structure */ +/* port_index Port index of insertion */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_device_remove Remove device */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_rh_device_extraction(UX_HCD *hcd, UINT port_index) +{ + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_RH_DEVICE_EXTRACTION, hcd, port_index, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Ask the stack to remove the device, pass the value 0 as the parent root hub. */ + _ux_host_stack_device_remove(hcd, 0, port_index); + + /* The device has been removed, so the port is free again. */ + hcd -> ux_hcd_rh_device_connection &= (ULONG)~(1 << port_index); + + /* That command should never fail! */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_rh_device_insertion.c b/common/core/src/ux_host_stack_rh_device_insertion.c new file mode 100644 index 0000000..fe08260 --- /dev/null +++ b/common/core/src/ux_host_stack_rh_device_insertion.c @@ -0,0 +1,170 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_rh_device_insertion PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles a device insertion on a downstream port of */ +/* the root hub pointed by HCD. */ +/* */ +/* INPUT */ +/* */ +/* HCD Pointer to HCD structure */ +/* port_index Port index of insertion */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_delay_ms Thread sleep */ +/* _ux_host_stack_new_device_create New device create */ +/* _ux_host_stack_device_remove Device remove */ +/* (hcd_entry_function) Entry function of HCD driver */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_rh_device_insertion(UX_HCD *hcd, UINT port_index) +{ + +UINT index_loop; +UINT device_speed; +ULONG port_status; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_RH_DEVICE_INSERTION, hcd, port_index, 0, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* Perform a PORT_ENABLE command. */ + port_status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_ENABLE_PORT, (VOID *)((ALIGN_TYPE)port_index)); + + /* Check return status. */ + if (port_status == UX_PORT_INDEX_UNKNOWN) + return(port_status); + + /* A debounce interval with a minimum duration of 100 ms on attach. */ + _ux_utility_delay_ms(100); + + /* The first attempts to do a device enumeration may fail. + Typically, after the port is reset and the first command is sent to + the device, there is no answer. In this case, we reset the port again + and retry. Usually that does the trick! */ + for (index_loop = 0; index_loop < UX_RH_ENUMERATION_RETRY; index_loop++) + { + + /* Now we have to do a PORT_RESET command. */ + port_status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_RESET_PORT, (VOID *)((ALIGN_TYPE)port_index)); + if (port_status == UX_SUCCESS) + { + + /* The port reset phase was successful. Before we invoke the device enumeration function, + we need to know the speed of the device. */ + port_status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_GET_PORT_STATUS, (VOID *)((ALIGN_TYPE)port_index)); + + /* Check return status. */ + if (port_status == UX_PORT_INDEX_UNKNOWN) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_ENUMERATION_FAILURE, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DEVICE_ENUMERATION_FAILURE); + } + + /* Set the device speed. */ + device_speed = port_status >> UX_PS_DS; + + /* Ask the USB stack to enumerate this device. A root hub is considered self + powered. */ + status = _ux_host_stack_new_device_create(hcd, UX_NULL, port_index, device_speed, UX_MAX_SELF_POWER); + + /* Check return status. */ + if (status == UX_SUCCESS) + { + + /* Successful device create. */ + + /* The device has been mounted properly, we have to remember this + so when the device is removed, we have to invoke the enumeration + function again */ + hcd -> ux_hcd_rh_device_connection |= (ULONG)(1 << port_index); + + /* Return success to the caller. */ + return(UX_SUCCESS); + } + else if (index_loop < UX_RH_ENUMERATION_RETRY - 1) + + /* Simulate remove to free allocated resources before retry. */ + _ux_host_stack_device_remove(hcd, UX_NULL, port_index); + } + + /* We get here if something did not go well. Either the port did not respond + well to the ENABLE\RESET phases or the device did not enumerate well + so we try again ! */ + _ux_utility_delay_ms(UX_RH_ENUMERATION_RETRY_DELAY); + } + + /* If we get here, the device did not enumerate completely. The device is still attached to the root + hub and therefore there is a physical connection with a unenumerated device. */ + hcd -> ux_hcd_rh_device_connection |= (ULONG)(1 << port_index); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_ENUMERATION_FAILURE, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return a failed enumeration. */ + return(UX_DEVICE_ENUMERATION_FAILURE); +} + diff --git a/common/core/src/ux_host_stack_role_swap.c b/common/core/src/ux_host_stack_role_swap.c new file mode 100644 index 0000000..f28b32a --- /dev/null +++ b/common/core/src/ux_host_stack_role_swap.c @@ -0,0 +1,115 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_role_swap PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when the host or the device demand a role */ +/* swap. This function may be called by an application or by the HNP */ +/* thread. */ +/* */ +/* INPUT */ +/* */ +/* hcd Pointer to HCD */ +/* device Device pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_host_stack_transfer_request Transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application of HNP thread. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_role_swap(UX_DEVICE *device) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; + + /* Retrieve the control endpoint and the transfer request associated with it. */ + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Perform a SET_FEATURE on this device to inform the it we are ready to change role. */ + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_SET_FEATURE; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_OTG_FEATURE_B_HNP_ENABLE; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the status fails, simply ignore the command but do not proceed. */ + if (status != UX_SUCCESS) + + /* We have an error. Do not proceed. */ + return(status); + + /* Keep track of the event for HNP synchronization. */ + _ux_system_otg -> ux_system_otg_change_mode_event = UX_OTG_HOST_TO_SLAVE; + + /* Call the OTG function that will perform the swap. */ + _ux_system_otg -> ux_system_otg_function(UX_OTG_HOST_TO_SLAVE); + + /* Reset the event. */ + _ux_system_otg -> ux_system_otg_change_mode_event = 0; + + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_host_stack_transfer_request.c b/common/core/src/ux_host_stack_transfer_request.c new file mode 100644 index 0000000..8c093be --- /dev/null +++ b/common/core/src/ux_host_stack_transfer_request.c @@ -0,0 +1,177 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_transfer_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a USB transaction. On entry the transfer */ +/* request gives the endpoint pipe selected for this transaction and */ +/* the parameters associated with the transfer (data payload, length */ +/* of transaction) */ +/* */ +/* For Control pipe, the transaction is blocking and will only return */ +/* when the 3 phases of the control transfer have been completed or if */ +/* there is a previous error. For other pipes, the USB stack will */ +/* schedule the transaction on the USB but will not wait for its */ +/* completion. Each request for non blocking pipes has to specify a */ +/* completion routine. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Transfer request structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status If UX_SUCCESS, transfer was */ +/* successfully started */ +/* */ +/* CALLS */ +/* */ +/* HCD Entry Function */ +/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_utility_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_transfer_request(UX_TRANSFER *transfer_request) +{ + +TX_INTERRUPT_SAVE_AREA + +UX_ENDPOINT *endpoint; +UX_DEVICE *device; +UX_HCD *hcd; +UINT status; + + + /* Get the endpoint container from the transfer_request */ + endpoint = transfer_request -> ux_transfer_request_endpoint; + + /* Get the device container from the endpoint. */ + device = endpoint -> ux_endpoint_device; + + /* Ensure we are not preempted by the enum thread while we check the device + state and set the transfer status. */ + TX_DISABLE + + /* We can only transfer when the device is ATTACHED, ADDRESSED OR CONFIGURED. */ + if ((device -> ux_device_state == UX_DEVICE_ATTACHED) || (device -> ux_device_state == UX_DEVICE_ADDRESSED) + || (device -> ux_device_state == UX_DEVICE_CONFIGURED)) + { + + /* Set the transfer to pending. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_STATUS_PENDING; + + /* Save the thread making this transfer. If we're under interrupt, this + will be null. */ + transfer_request -> ux_transfer_request_thread_pending = _ux_utility_thread_identify(); + } + else + { + + /* The device is in an invalid state. Restore interrupts and return error. */ + TX_RESTORE + + /* Check if this is endpoint 0. */ + if ((endpoint -> ux_endpoint_descriptor.bEndpointAddress & (UINT)~UX_ENDPOINT_DIRECTION) == 0) + { + + /* Check if the class has already protected it. */ + if (device -> ux_device_protection_semaphore.tx_semaphore_count == 0) + { + + /* Class is using endpoint 0. Unprotect semaphore. */ + _ux_utility_semaphore_put(&device -> ux_device_protection_semaphore); + } + } + + return(UX_TRANSFER_NOT_READY); + } + + /* Restore interrupts. */ + TX_RESTORE + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_TRANSFER_REQUEST, device, endpoint, transfer_request, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* With the device we have the pointer to the HCD. */ + hcd = device -> ux_device_hcd; + + /* If this is endpoint 0, we protect the endpoint from a possible re-entry. */ + if ((endpoint -> ux_endpoint_descriptor.bEndpointAddress & (UINT)~UX_ENDPOINT_DIRECTION) == 0) + { + + /* Check if the class has already protected it. */ + if (device -> ux_device_protection_semaphore.tx_semaphore_count != 0) + { + + /* We are using endpoint 0. Protect with semaphore. */ + status = _ux_utility_semaphore_get(&device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + + /* Something went wrong. */ + return(status); + } + } + + /* Send the command to the controller. */ + status = hcd -> ux_hcd_entry_function(hcd, UX_HCD_TRANSFER_REQUEST, transfer_request); + + /* If this is endpoint 0, we unprotect the endpoint. */ + if ((endpoint -> ux_endpoint_descriptor.bEndpointAddress & (UINT)~UX_ENDPOINT_DIRECTION) == 0) + + /* We are using endpoint 0. Unprotect with semaphore. */ + _ux_utility_semaphore_put(&device -> ux_device_protection_semaphore); + + /* And return the status. */ + return(status); +} diff --git a/common/core/src/ux_host_stack_transfer_request_abort.c b/common/core/src/ux_host_stack_transfer_request_abort.c new file mode 100644 index 0000000..cbdaa19 --- /dev/null +++ b/common/core/src/ux_host_stack_transfer_request_abort.c @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_stack_transfer_request_abort PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function aborts a pending transfer request that has been */ +/* previously submitted. This function only cancels the specific */ +/* transfer request. */ +/* */ +/* The call back to the function will have the */ +/* UX_TRANSFER_STATUS_ABORT status. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Transfer request structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status If UX_SUCCESS, transfer was */ +/* successfully aborted */ +/* */ +/* CALLS */ +/* */ +/* HCD Entry Function */ +/* Transfer Completion Function */ +/* _ux_utility_semaphore_put Put semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_stack_transfer_request_abort(UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_DEVICE *device; +UX_HCD *hcd; +ULONG completion_code; + + + /* Get the endpoint container from the transfer request. */ + endpoint = transfer_request -> ux_transfer_request_endpoint; + + /* Get the device container from the endpoint. */ + device = endpoint -> ux_endpoint_device; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_STACK_TRANSFER_REQUEST_ABORT, device, endpoint, transfer_request, 0, UX_TRACE_HOST_STACK_EVENTS, 0, 0) + + /* With the device we have the pointer to the HCD. */ + hcd = device -> ux_device_hcd; + + /* Check pending transaction. */ + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + { + + /* Send the abort command to the controller. */ + hcd -> ux_hcd_entry_function(hcd, UX_HCD_TRANSFER_ABORT, transfer_request); + + /* Save the completion code since we're about to set it to ABORT. The + reason we can't just assume its value is PENDING is that in between + the completion code check and this line, it's possible that the transfer + completed, which would've changed the completion code to SUCCESS. + Such a case is valid, and we want to make sure we don't put() the + transfer request's semaphore again. */ + completion_code = transfer_request -> ux_transfer_request_completion_code; + + /* Set the transfer_request status to abort. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_STATUS_ABORT; + + /* We need to inform the class that owns this transfer_request of the + abort if there is a call back mechanism. */ + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + + /* Is a thread waiting on the semaphore? */ + if (/* Is the transfer pending? */ + completion_code == UX_TRANSFER_STATUS_PENDING && + /* Is the thread waiting not this one? (clearly we're not waiting!) */ + transfer_request -> ux_transfer_request_thread_pending != _ux_utility_thread_identify() && + /* Does the transfer request not have a completion function? */ + transfer_request -> ux_transfer_request_completion_function == UX_NULL) + + /* Wake up the semaphore for this request. */ + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + } + + /* This function never fails! */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_system_error_handler.c b/common/core/src/ux_system_error_handler.c new file mode 100644 index 0000000..530c925 --- /dev/null +++ b/common/core/src/ux_system_error_handler.c @@ -0,0 +1,87 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** System */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_system_error_handler PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function saves the last critical error from USBX functions. */ +/* It is mainly used for debugging purpose to trap where error occurred*/ +/* */ +/* */ +/* INPUT */ +/* */ +/* error_code */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_system_error_handler(UINT system_level, UINT system_context, UINT error_code) +{ + + /* Save the last system error code. */ + _ux_system -> ux_system_last_error = error_code; + + /* Increment the total number of system errors. */ + _ux_system -> ux_system_error_count++; + + /* Is there an application call back function to call ? */ + if (_ux_system -> ux_system_error_callback_function != UX_NULL) + { + + /* The callback function is defined, call it. */ + _ux_system -> ux_system_error_callback_function(system_level, system_context, error_code); + } +} diff --git a/common/core/src/ux_system_initialize.c b/common/core/src/ux_system_initialize.c new file mode 100644 index 0000000..b232f8d --- /dev/null +++ b/common/core/src/ux_system_initialize.c @@ -0,0 +1,241 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** System */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Define UX_SYSTEM_INIT to bring in the USBX version ID string. */ + +#define UX_SYSTEM_INIT + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_system.h" + +/* Define the USBX system data structure. */ + +UX_SYSTEM *_ux_system; +UX_SYSTEM_OTG *_ux_system_otg; + +/* Define names of all the packed descriptors in USBX. */ + +UCHAR _ux_system_endpoint_descriptor_structure[] = {1,1,1,1,2,1 }; +UCHAR _ux_system_device_descriptor_structure[] = {1,1,2,1,1,1,1,2,2,2,1,1,1,1}; +UCHAR _ux_system_configuration_descriptor_structure[] = {1,1,2,1,1,1,1,1}; +UCHAR _ux_system_interface_descriptor_structure[] = {1,1,1,1,1,1,1,1,1}; +UCHAR _ux_system_interface_association_descriptor_structure[] = {1,1,1,1,1,1,1,1}; +UCHAR _ux_system_string_descriptor_structure[] = {1,1,2}; +UCHAR _ux_system_dfu_functional_descriptor_structure[] = {1,1,1,2,2,2}; +UCHAR _ux_system_class_audio_interface_descriptor_structure[] = {1,1,1,1,1,1,1,1}; +UCHAR _ux_system_class_audio_input_terminal_descriptor_structure[] = {1,1,1,1,2,1,1,2,1,1}; +UCHAR _ux_system_class_audio_output_terminal_descriptor_structure[] = {1,1,1,1,2,1,1,1}; +UCHAR _ux_system_class_audio_feature_unit_descriptor_structure[] = {1,1,1,1,1,1,1}; +UCHAR _ux_system_class_audio_streaming_interface_descriptor_structure[] = {1,1,1,1,1,1}; +UCHAR _ux_system_class_audio_streaming_endpoint_descriptor_structure[] = {1,1,1,1,1,1}; +UCHAR _ux_system_hub_descriptor_structure[] = {1,1,1,2,1,1,1,1}; +UCHAR _ux_system_hid_descriptor_structure[] = {1,1,2,1,1,1,2}; +UCHAR _ux_system_class_pima_storage_structure[] = {2,2,2,4,4,4,4,4}; +UCHAR _ux_system_class_pima_object_structure[] = {4,2,2,4,2,4,4,4,4,4,4,4,2,4,4}; +UCHAR _ux_system_ecm_interface_descriptor_structure[] = {1,1,1,1,4,2,2,1}; + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_system_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the various control data structures for */ +/* the USBX system. */ +/* */ +/* INPUT */ +/* */ +/* regular_memory_pool_start Start of non cached memory pool */ +/* regular_memory_size Size of non cached memory pool */ +/* cache_safe_memory_pool_start Start of cached memory pool */ +/* cache_safe_memory_size Size of cached memory pool */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_set Set memory */ +/* _ux_utility_mutex_create Create mutex */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_system_initialize(VOID *regular_memory_pool_start, ULONG regular_memory_size, + VOID *cache_safe_memory_pool_start, ULONG cache_safe_memory_size) +{ + +UX_MEMORY_BLOCK *memory_block; +ALIGN_TYPE int_memory_pool_start; +VOID *regular_memory_pool_end; +UINT status; +ULONG memory_pool_offset; + + /* Reset memory block */ + _ux_utility_memory_set(regular_memory_pool_start, 0, regular_memory_size); + + /* Set the _ux_system structure at the start of our regular memory */ + _ux_system = (UX_SYSTEM *) regular_memory_pool_start; + + /* Add to the memory offset the size of the allocated block. */ + memory_pool_offset = sizeof(UX_SYSTEM); + +#ifndef UX_DEVICE_SIDE_ONLY + + /* Set the _ux_system_host structure. */ + _ux_system_host = (UX_SYSTEM_HOST *) (((UCHAR *) regular_memory_pool_start) + memory_pool_offset); + + /* Add to the memory offset the size of the allocated block. */ + memory_pool_offset += (ULONG)sizeof(UX_SYSTEM_HOST); + +#endif + +#ifndef UX_HOST_SIDE_ONLY + + /* Set the _ux_system_slave structure. */ + _ux_system_slave = (UX_SYSTEM_SLAVE *) (((UCHAR *) regular_memory_pool_start) + memory_pool_offset); + + /* Add to the memory offset the size of the allocated block. */ + memory_pool_offset += (ULONG)sizeof(UX_SYSTEM_SLAVE); + +#endif + + +#ifdef UX_OTG_SUPPORT + + /* Set the _ux_system_otg structure. */ + _ux_system_otg = (UX_SYSTEM_OTG *) (((UCHAR *) regular_memory_pool_start) + memory_pool_offset); + + /* Add to the memory offset the size of the allocated block. */ + memory_pool_offset += (ULONG)sizeof(UX_SYSTEM_OTG); +#endif + + + /* Set the cache safe memory for the dynamic pool */ + _ux_system -> ux_system_regular_memory_pool_start = (UX_MEMORY_BLOCK *) (((UCHAR *) regular_memory_pool_start) + + memory_pool_offset); + + /* Make sure the regular memory pool is aligned properly */ + int_memory_pool_start = (ALIGN_TYPE) _ux_system -> ux_system_regular_memory_pool_start; + int_memory_pool_start += UX_ALIGN_MIN; + int_memory_pool_start &= ~((ALIGN_TYPE)UX_ALIGN_MIN); + + /* Set the end of the regular memory pool. */ + regular_memory_pool_end = (void *) (((UCHAR *) regular_memory_pool_start) + regular_memory_size); + + /* Check if we have memory available. */ + if (int_memory_pool_start >= (ALIGN_TYPE)regular_memory_pool_end) + { + + /* No memory available. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Now, we have a project structure allocated, save the regular memory allocation details */ + _ux_system -> ux_system_regular_memory_pool_size = (ULONG) (((ALIGN_TYPE) regular_memory_pool_end) - int_memory_pool_start); + _ux_system -> ux_system_regular_memory_pool_free = _ux_system -> ux_system_regular_memory_pool_size; + _ux_system -> ux_system_regular_memory_pool_start = (UX_MEMORY_BLOCK *) int_memory_pool_start; + + /* Build the first free memory block */ + memory_block = _ux_system -> ux_system_regular_memory_pool_start; + memory_block -> ux_memory_block_size = _ux_system -> ux_system_regular_memory_pool_size - (ULONG)sizeof(UX_MEMORY_BLOCK); + memory_block -> ux_memory_block_status = UX_MEMORY_UNUSED; + + /* Check the definition of the cache safe pool. If the application or controller do not require any cache safe memory, + define the cached safe memory region as the regular memory region. */ + if (cache_safe_memory_pool_start == UX_NULL) + { + + /* Cache safe memory is the same as regular memory. */ + _ux_system -> ux_system_cache_safe_memory_pool_size = _ux_system -> ux_system_regular_memory_pool_size; + _ux_system -> ux_system_cache_safe_memory_pool_free = _ux_system -> ux_system_regular_memory_pool_free; + _ux_system -> ux_system_cache_safe_memory_pool_start = _ux_system -> ux_system_regular_memory_pool_start; + } + else + { + + /* Make sure the cache safe memory pool is aligned properly */ + int_memory_pool_start = (ALIGN_TYPE) cache_safe_memory_pool_start; + int_memory_pool_start += UX_ALIGN_MIN; + int_memory_pool_start &= ~((ALIGN_TYPE)UX_ALIGN_MIN); + + /* Save the cache safe memory allocation details */ + _ux_system -> ux_system_cache_safe_memory_pool_size = cache_safe_memory_size - UX_ALIGN_MIN; + _ux_system -> ux_system_cache_safe_memory_pool_free = _ux_system -> ux_system_cache_safe_memory_pool_size; + _ux_system -> ux_system_cache_safe_memory_pool_start = (UX_MEMORY_BLOCK *) int_memory_pool_start; + + /* Reset this memory block */ + _ux_utility_memory_set(_ux_system -> ux_system_cache_safe_memory_pool_start, 0, _ux_system -> ux_system_cache_safe_memory_pool_size); + + /* Build the first free memory block */ + memory_block = _ux_system -> ux_system_cache_safe_memory_pool_start; + memory_block -> ux_memory_block_size = _ux_system -> ux_system_cache_safe_memory_pool_size - (ULONG)sizeof(UX_MEMORY_BLOCK); + memory_block -> ux_memory_block_status = UX_MEMORY_UNUSED; + } + +#ifdef UX_ENABLE_DEBUG_LOG + + /* Obtain memory for storing the debug log. */ + _ux_system -> ux_system_debug_log_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_DEBUG_LOG_SIZE); + if (_ux_system -> ux_system_debug_log_buffer == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Setup the head and tail pointers. */ + _ux_system -> ux_system_debug_log_head = _ux_system -> ux_system_debug_log_buffer; + _ux_system -> ux_system_debug_log_tail = _ux_system -> ux_system_debug_log_buffer; + + /* Keep the size in system structure variable. */ + _ux_system -> ux_system_debug_log_size = UX_DEBUG_LOG_SIZE; + +#endif + + /* Create the Mutex object used by USBX to control critical sections. */ + status = _ux_utility_mutex_create(&_ux_system -> ux_system_mutex, "ux_system_mutex"); + if(status != UX_SUCCESS) + return(UX_MUTEX_ERROR); + + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_system_uninitialize.c b/common/core/src/ux_system_uninitialize.c new file mode 100644 index 0000000..c00a36a --- /dev/null +++ b/common/core/src/ux_system_uninitialize.c @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** System */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_system.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_system_uninitialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function uninitializes the various control data structures for */ +/* the USBX system. */ +/* */ +/* INPUT */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_mutex_delete ThreadX delete mutex */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_system_uninitialize(VOID) +{ + + /* Delete the Mutex object used by USBX to control critical sections. */ + _ux_utility_mutex_delete(&_ux_system -> ux_system_mutex); + + return(UX_SUCCESS); +} + + diff --git a/common/core/src/ux_trace_event_insert.c b/common/core/src/ux_trace_event_insert.c new file mode 100644 index 0000000..33ae201 --- /dev/null +++ b/common/core/src/ux_trace_event_insert.c @@ -0,0 +1,140 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef UX_SOURCE_CODE +#define UX_SOURCE_CODE +#endif + + +/* Include necessary system files. */ + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_trace_event_insert PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function inserts a USBX event into the current trace buffer. */ +/* */ +/* INPUT */ +/* */ +/* event_id User Event ID */ +/* info_field_1 First information field */ +/* info_field_2 First information field */ +/* info_field_3 First information field */ +/* info_field_4 First information field */ +/* current_event Current event pointer for */ +/* post event update */ +/* current_timestamp Timestamp for post event */ +/* update */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Internal USBX Functions */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +#ifdef UX_TRACE_INSERT_MACROS +VOID _ux_trace_event_insert(ULONG event_id, ULONG info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4, + ULONG filter, TX_TRACE_BUFFER_ENTRY **current_event, ULONG *current_timestamp) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_TRACE_BUFFER_ENTRY *event; +ULONG timestamp; + + + /* Disable interrupts. */ + TX_DISABLE + + /* Pickup the current event. */ + event = _tx_trace_buffer_current_ptr; + + /* Insert this event into the trace buffer. */ + TX_TRACE_IN_LINE_INSERT(event_id, info_field_1, info_field_2, info_field_3, info_field_4, filter) + + /* Initialize the timestamp to 0. */ + timestamp = 0; + + /* Determine if the event was inserted. */ + if (event) + { + + /* Was the event inserted? */ + if (event -> tx_trace_buffer_entry_event_id == event_id) + { + + /* Yes, the event was inserted in the event trace so pickup the timestamp. */ + timestamp = event -> tx_trace_buffer_entry_time_stamp; + } + else + { + + /* Event was not inserted, simply set the event pointer to NULL. */ + event = UX_NULL; + } + } + + /* Now determine if the caller requested the current event. */ + if (current_event) + { + + /* Yes, return the event pointer of potential subsequent update. */ + *current_event = event; + } + + /* Now determine if the current timestamp was requested. */ + if (current_timestamp) + { + + /* Yes, return the current timestamp. */ + *current_timestamp = timestamp; + } + + /* Restore interrupts. */ + TX_RESTORE +} +#endif + diff --git a/common/core/src/ux_trace_event_update.c b/common/core/src/ux_trace_event_update.c new file mode 100644 index 0000000..516f783 --- /dev/null +++ b/common/core/src/ux_trace_event_update.c @@ -0,0 +1,128 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef UX_SOURCE_CODE +#define UX_SOURCE_CODE +#endif + + +/* Include necessary system files. */ + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_trace_event_update PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function inserts a USBX event into the current trace buffer. */ +/* */ +/* INPUT */ +/* */ +/* event Event pointer */ +/* timestamp Timestamp of the event */ +/* event_id User Event ID */ +/* info_field_1 First information field */ +/* info_field_2 First information field */ +/* info_field_3 First information field */ +/* info_field_4 First information field */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Internal USBX Functions */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +#ifdef UX_TRACE_INSERT_MACROS +VOID _ux_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, ULONG event_id, ULONG info_field_1, ULONG info_field_2, ULONG info_field_3, ULONG info_field_4) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* Determine if the event exists and is still the event originally inserted into the trace. */ + if ((event) && (event -> tx_trace_buffer_entry_event_id == event_id) && (event -> tx_trace_buffer_entry_time_stamp == timestamp)) + { + + /* Yes, update this trace entry based on the info input parameters. */ + + /* Check for info field 1 update. */ + if (info_field_1) + { + + /* Yes, update info field 1. */ + event -> tx_trace_buffer_entry_information_field_1 = info_field_1; + } + + /* Check for info field 2 update. */ + if (info_field_2) + { + + /* Yes, update info field 2. */ + event -> tx_trace_buffer_entry_information_field_2 = info_field_2; + } + + /* Check for info field 3 update. */ + if (info_field_3) + { + + /* Yes, update info field 3. */ + event -> tx_trace_buffer_entry_information_field_3 = info_field_3; + } + + /* Check for info field 4 update. */ + if (info_field_4) + { + + /* Yes, update info field 4. */ + event -> tx_trace_buffer_entry_information_field_4 = info_field_4; + } + } + /* Restore interrupts. */ + TX_RESTORE +} +#endif + diff --git a/common/core/src/ux_trace_object_register.c b/common/core/src/ux_trace_object_register.c new file mode 100644 index 0000000..8a1758f --- /dev/null +++ b/common/core/src/ux_trace_object_register.c @@ -0,0 +1,91 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef UX_SOURCE_CODE +#define UX_SOURCE_CODE +#endif + + +/* Include necessary system files. */ + +#include "ux_api.h" + +#ifdef UX_TRACE_INSERT_MACROS +extern VOID _tx_trace_object_register(UCHAR , VOID *, CHAR *, ULONG , ULONG ); +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_trace_object_register PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers a USBX object in the trace registry. */ +/* */ +/* INPUT */ +/* */ +/* object_type Type of system object */ +/* object_ptr Address of system object */ +/* object_name Name of system object */ +/* parameter_1 Supplemental parameter 1 */ +/* parameter_2 Supplemental parameter 2 */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_trace_object_register Actual register function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* Call actual object register function. */ + _tx_trace_object_register(object_type, object_ptr, object_name, parameter_1, parameter_2); + + /* Restore interrupts. */ + TX_RESTORE +} +#endif + diff --git a/common/core/src/ux_trace_object_unregister.c b/common/core/src/ux_trace_object_unregister.c new file mode 100644 index 0000000..88417db --- /dev/null +++ b/common/core/src/ux_trace_object_unregister.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Trace */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef UX_SOURCE_CODE +#define UX_SOURCE_CODE +#endif + + +/* Include necessary system files. */ + +#include "ux_api.h" + +#ifdef UX_TRACE_INSERT_MACROS +extern VOID _tx_trace_object_unregister(VOID *); +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_trace_object_unregister PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function unregisters a USBX object in the trace registry. */ +/* */ +/* INPUT */ +/* */ +/* object_pointer Address of system object */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_trace_object_unregister Actual unregister function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX delete functions */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_trace_object_unregister(VOID *object_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + + + /* Disable interrupts. */ + TX_DISABLE + + /* Call actual object unregister function. */ + _tx_trace_object_unregister(object_ptr); + + /* Restore interrupts. */ + TX_RESTORE +} +#endif diff --git a/common/core/src/ux_utility_debug_callback_register.c b/common/core/src/ux_utility_debug_callback_register.c new file mode 100644 index 0000000..59b35c4 --- /dev/null +++ b/common/core/src/ux_utility_debug_callback_register.c @@ -0,0 +1,83 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +#ifdef UX_ENABLE_DEBUG_LOG + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_debug_callback_register PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers a callback for sending formatted debug */ +/* messages to the application. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* debug_callback */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_debug_callback_register(VOID (*debug_callback)(UCHAR *, ULONG)) + +{ + + /* The callback function is defined. */ + _ux_system -> ux_system_debug_callback_function = debug_callback; + + /* We are done here. No return codes. */ + return; +} + +#endif diff --git a/common/core/src/ux_utility_debug_log.c b/common/core/src/ux_utility_debug_log.c new file mode 100644 index 0000000..a7fdddf --- /dev/null +++ b/common/core/src/ux_utility_debug_log.c @@ -0,0 +1,310 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +#ifdef UX_ENABLE_DEBUG_LOG + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_debug_log PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function logs a debug msg in a circular queue. The queue */ +/* must be initialized during the init of USBX. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* debug_location C string to locate the debug, */ +/* for example source file name. */ +/* debug_message C string of message */ +/* debug_code Debug code */ +/* debug_parameter_1 First parameter */ +/* debug_parameter_2 Second parameter */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_string_length_check Check C string and return */ +/* its length if null-terminated */ +/* _tx_time_get Return system clock time */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_debug_log(UCHAR *debug_location, UCHAR *debug_message, ULONG debug_code, + ULONG debug_parameter_1, ULONG debug_parameter_2) +{ + +UINT debug_location_string_length; +UINT debug_message_string_length; +ULONG total_debug_message_length; +ULONG parameter_length; +ULONG parameter_shift; +UCHAR parameter_hexa; +ULONG local_parameter_value; +ULONG current_time; +TX_INTERRUPT_SAVE_AREA + + /* Is USBX system completely initialized ? */ + if (_ux_system -> ux_system_debug_log_size == 0) + + /* Not yet. */ + return; + + /* Entering critical area. Disable interrupts. */ + TX_DISABLE + + /* Store the debug value as the last debug value recorded. */ + _ux_system -> ux_system_debug_code = debug_code; + + /* Increment the debug value code count. */ + _ux_system -> ux_system_debug_count++; + + /* Calculate the string length. */ + debug_location_string_length = UX_DEBUG_LOG_SIZE; + _ux_utility_string_length_check(source, &debug_location_string_length, UX_DEBUG_LOG_SIZE); + debug_message_string_length = UX_DEBUG_LOG_SIZE; + _ux_utility_string_length_check(source, &debug_message_string_length, UX_DEBUG_LOG_SIZE); + + /* Calculate the length of the entire message string. 1 fixed string, then 1 hexa + decimal, then 2 strings then 2 hexa decimal numbers in the format 0x00000000 + separated by commas and . at the end, zero terminated. */ + total_debug_message_length = debug_location_string_length + debug_message_string_length + 10 + 10 + 10 + 10 + 5; + + /* Can we accommodate this debug value message at the current location ? */ + if (_ux_system -> ux_system_debug_log_head + total_debug_message_length > _ux_system -> ux_system_debug_log_buffer + _ux_system -> ux_system_debug_log_size) + { + + /* The debug value log to insert goes beyond the end of the log buffer, rewind to the beginning. */ + _ux_system -> ux_system_debug_log_head = _ux_system -> ux_system_debug_log_buffer; + } + + /* Copy the time strings and parameters in the log buffer. */ + _ux_utility_memory_copy(_ux_system -> ux_system_debug_log_head, "At time : ", 10); + _ux_system -> ux_system_debug_log_head += 10; + + /* Get the time value from TX. */ + current_time = _tx_time_get(); + + /* Reset the value of the length.*/ + parameter_length = 0; + + /* Init the shift value. */ + parameter_shift = 32 - 4; + + /* We parse the hexa value parameter and build the hexa value one byte at a type. */ + while(parameter_length < 8) + { + + /* Shift the 4 bit value we are interested in. We keep the lowest nibble. */ + local_parameter_value = (current_time >> parameter_shift) & 0x0f; + + /* See if this value is from 0-9 or A to F. */ + if (local_parameter_value <= 9) + + /* We have a digit. */ + parameter_hexa = (UCHAR) (local_parameter_value + '0'); + + else + + /* We have 'A' to 'F' value. */ + parameter_hexa = (UCHAR) (local_parameter_value - 10 + 'A'); + + /* Store the converted hexa value. */ + *_ux_system -> ux_system_debug_log_head = parameter_hexa; + + /* Next position. */ + _ux_system -> ux_system_debug_log_head++; + + /* Update length. */ + parameter_length++; + + /* Continue shifting by one nibble. */ + parameter_shift = parameter_shift - 4; + } + + /* Add the comma after the time. */ + *_ux_system -> ux_system_debug_log_head = ','; + _ux_system -> ux_system_debug_log_head++; + + /* Copy the strings and parameters in the log buffer. */ + _ux_utility_memory_copy(_ux_system -> ux_system_debug_log_head, debug_location, debug_location_string_length); + _ux_system -> ux_system_debug_log_head += debug_location_string_length; + *_ux_system -> ux_system_debug_log_head = ','; + _ux_system -> ux_system_debug_log_head++; + _ux_utility_memory_copy(_ux_system -> ux_system_debug_log_head, debug_message, debug_message_string_length); + _ux_system -> ux_system_debug_log_head += debug_message_string_length; + *_ux_system -> ux_system_debug_log_head = ','; + _ux_system -> ux_system_debug_log_head++; + + /* Create the hexa string for parameter 1. */ + *_ux_system -> ux_system_debug_log_head = '0'; + _ux_system -> ux_system_debug_log_head++; + *_ux_system -> ux_system_debug_log_head = 'x'; + _ux_system -> ux_system_debug_log_head++; + + /* Reset the value of the length.*/ + parameter_length = 0; + + /* Init the shift value. */ + parameter_shift = 32 - 4; + + /* We parse the hexa value parameter and build the hexa value one byte at a type. */ + while(parameter_length < 8) + { + + /* Shift the 4 bit value we are interested in. We keep the lowest nibble. */ + local_parameter_value = (debug_parameter_1 >> parameter_shift) & 0x0f; + + /* See if this value is from 0-9 or A to F. */ + if (local_parameter_value <= 9) + + /* We have a digit. */ + parameter_hexa = (UCHAR) (local_parameter_value + '0'); + + else + + /* We have 'A' to 'F' value. */ + parameter_hexa = (UCHAR) (local_parameter_value - 10 + 'A'); + + /* Store the converted hexa value. */ + *_ux_system -> ux_system_debug_log_head = parameter_hexa; + + /* Next position. */ + _ux_system -> ux_system_debug_log_head++; + + /* Update length. */ + parameter_length++; + + /* Continue shifting by one nibble. */ + parameter_shift = parameter_shift - 4; + } + + /* Add the comma between the 2 hexa values. */ + *_ux_system -> ux_system_debug_log_head = ','; + _ux_system -> ux_system_debug_log_head++; + + /* Create the hexa string for parameter 2. */ + *_ux_system -> ux_system_debug_log_head = '0'; + _ux_system -> ux_system_debug_log_head++; + *_ux_system -> ux_system_debug_log_head = 'x'; + _ux_system -> ux_system_debug_log_head++; + + /* Reset the value of the length.*/ + parameter_length = 0; + + /* Init the shift value. */ + parameter_shift = 32 - 4; + + /* We parse the hexa value parameter and build the hexa value one byte at a type. */ + while(parameter_length < 8) + { + + /* Shift the 4 bit value we are interested in. We keep the lowest nibble. */ + local_parameter_value = (debug_parameter_2 >> parameter_shift) & 0x0f; + + /* See if this value is from 0-9 or A to F. */ + if (local_parameter_value <= 9) + + /* We have a digit. */ + parameter_hexa = (UCHAR) (local_parameter_value + '0'); + + else + + /* We have 'A' to 'F' value. */ + parameter_hexa = (UCHAR) (local_parameter_value - 10 + 'A'); + + /* Store the converted hexa value. */ + *_ux_system -> ux_system_debug_log_head = parameter_hexa; + + /* Next position. */ + _ux_system -> ux_system_debug_log_head++; + + /* Update length. */ + parameter_length++; + + /* Continue shifting by one nibble. */ + parameter_shift = parameter_shift - 4; + } + + /* Add the termination dot at the end. */ + *_ux_system -> ux_system_debug_log_head = '.'; + _ux_system -> ux_system_debug_log_head++; + + /* Add the CR/LF end of the string. */ + *_ux_system -> ux_system_debug_log_head = 0x0d; + _ux_system -> ux_system_debug_log_head++; + *_ux_system -> ux_system_debug_log_head = 0x0a; + _ux_system -> ux_system_debug_log_head++; + + /* Add the zero end of the string. */ + *_ux_system -> ux_system_debug_log_head = 0x00; + _ux_system -> ux_system_debug_log_head++; + + /* The log string is put into the log buffer. It can stay here until + a break into debugger by the developer or be passed to a callback registered + by the application. */ + if (_ux_system -> ux_system_debug_callback_function != UX_NULL) + { + + /* The callback function is defined, call it. */ + _ux_system -> ux_system_debug_callback_function(_ux_system -> ux_system_debug_log_tail, debug_code); + + /* Update the tail. */ + _ux_system -> ux_system_debug_log_tail += total_debug_message_length; + + } + + /* Restore interrupts. */ + TX_RESTORE + + /* We are done here. No return codes. */ + return; +} + +#endif diff --git a/common/core/src/ux_utility_delay_ms.c b/common/core/src/ux_utility_delay_ms.c new file mode 100644 index 0000000..78c1dc8 --- /dev/null +++ b/common/core/src/ux_utility_delay_ms.c @@ -0,0 +1,87 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_delay_ms PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function causes the calling thread to sleep for the */ +/* specified number of milliseconds */ +/* */ +/* INPUT */ +/* */ +/* ms_wait Number of milliseconds to */ +/* wait for */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_sleep ThreadX sleep function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_delay_ms(ULONG ms_wait) +{ + +ULONG ticks; + + /* translate ms into ticks. */ + ticks = (ms_wait * UX_PERIODIC_RATE) / 1000; + + /* For safety add 1 to ticks. */ + ticks++; + + /* Call ThreadX sleep function. */ + tx_thread_sleep(ticks); + + /* Return completion status. */ + return; +} + diff --git a/common/core/src/ux_utility_descriptor_pack.c b/common/core/src/ux_utility_descriptor_pack.c new file mode 100644 index 0000000..6db1b61 --- /dev/null +++ b/common/core/src/ux_utility_descriptor_pack.c @@ -0,0 +1,114 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_descriptor_pack PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will pack an application structure into a USB */ +/* descriptor. */ +/* */ +/* INPUT */ +/* */ +/* descriptor Pointer to the unpacked */ +/* descriptor */ +/* descriptor_structure Components of the descriptor */ +/* descriptor_entries Number of entries in the */ +/* descriptor */ +/* raw_descriptor Pointer to packed descriptor */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_descriptor_pack(UCHAR * descriptor, UCHAR * descriptor_structure, + UINT descriptor_entries, UCHAR * raw_descriptor) +{ + + /* Loop on all the entries in this descriptor. */ + while(descriptor_entries--) + { + + /* Get the length of that component. */ + switch(*descriptor_structure++) + { + + /* Check the size then build the component from the source and + insert it into the target descriptor. */ + case 4: + + _ux_utility_long_put(raw_descriptor, *((ULONG *) descriptor)); + raw_descriptor += 4; + break; + + case 2: + + _ux_utility_short_put(raw_descriptor, (USHORT)*((ULONG *) descriptor)); + raw_descriptor += 2; + break; + + default: + + *raw_descriptor = (UCHAR) *((ULONG *) descriptor); + raw_descriptor++; + } + + /* Add the size of the component to the destination. */ + descriptor += 4; + } + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_utility_descriptor_parse.c b/common/core/src/ux_utility_descriptor_parse.c new file mode 100644 index 0000000..496a406 --- /dev/null +++ b/common/core/src/ux_utility_descriptor_parse.c @@ -0,0 +1,114 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_descriptor_parse PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will unpack a USB descriptor from the bus into a */ +/* memory aligned structure. */ +/* */ +/* INPUT */ +/* */ +/* raw_descriptor Pointer to packed descriptor */ +/* descriptor_structure Components of the descriptor */ +/* descriptor_entries Number of entries in the */ +/* descriptor */ +/* descriptor Pointer to the unpacked */ +/* descriptor */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_long_get Get 32-bit value */ +/* _ux_utility_short_get Get 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_descriptor_parse(UCHAR * raw_descriptor, UCHAR * descriptor_structure, + UINT descriptor_entries, UCHAR * descriptor) +{ + + /* Loop on all the entries in this descriptor. */ + while(descriptor_entries--) + { + + /* Get the length of that component. */ + switch(*descriptor_structure++) + { + + /* Check the size then build the component from the source and + insert it into the target descriptor. */ + case 4: + + *((ULONG *) descriptor) = _ux_utility_long_get(raw_descriptor); + raw_descriptor += 4; + break; + + case 2: + + *((ULONG *) descriptor) = (ULONG) _ux_utility_short_get(raw_descriptor); + raw_descriptor += 2; + break; + + default: + + *((ULONG *) descriptor) = (ULONG) *raw_descriptor; + raw_descriptor++; + } + + /* Add the size of the component to the destination. */ + descriptor += 4; + } + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_utility_error_callback_register.c b/common/core/src/ux_utility_error_callback_register.c new file mode 100644 index 0000000..cf77f0f --- /dev/null +++ b/common/core/src/ux_utility_error_callback_register.c @@ -0,0 +1,78 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_error_callback_register PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers a callback for sending formatted errors to */ +/* the application. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* error_callback */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_error_callback_register(VOID (*error_callback)(UINT system_level, UINT system_context, UINT error_code)) + +{ + + /* The callback function is defined. */ + _ux_system -> ux_system_error_callback_function = error_callback; + + /* We are done here. No return codes. */ + return; +} diff --git a/common/core/src/ux_utility_event_flags_create.c b/common/core/src/ux_utility_event_flags_create.c new file mode 100644 index 0000000..8d43c58 --- /dev/null +++ b/common/core/src/ux_utility_event_flags_create.c @@ -0,0 +1,91 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_event_flags_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a threadx group of flags */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Event flag control group */ +/* name Pointer to thread name string */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_event_flags_create ThreadX create event flag */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name) +{ + +UINT status; + + /* Call ThreadX to create the event flags. */ + status = tx_event_flags_create(group_ptr, name); + + /* Check for status. */ + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, UX_EVENT_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_EVENT_ERROR, group_ptr, 0, 0, UX_TRACE_ERRORS, 0, 0) + + } + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_event_flags_delete.c b/common/core/src/ux_utility_event_flags_delete.c new file mode 100644 index 0000000..e6ed879 --- /dev/null +++ b/common/core/src/ux_utility_event_flags_delete.c @@ -0,0 +1,79 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_event_flags_delete PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a threadx group of flags */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Event flag control group */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_event_flags_delete ThreadX delete event flag */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr) +{ + +UINT status; + + /* Call ThreadX to delete the event flags. */ + status = tx_event_flags_delete(group_ptr); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_event_flags_get.c b/common/core/src/ux_utility_event_flags_get.c new file mode 100644 index 0000000..ee634a4 --- /dev/null +++ b/common/core/src/ux_utility_event_flags_get.c @@ -0,0 +1,89 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_event_flags_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function get event flags from event flag group */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Event flag control group */ +/* requested_flags 32 bits variable event flags */ +/* get_option AND/OR/CLEAR ... options */ +/* actual_flag_ptr where the flags are placed */ +/* wait_option waiting option */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_event_flags_get ThreadX get event flag */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags, + UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option) +{ + +UINT status; +ULONG local_actual_flags_ptr; + + /* Call ThreadX to get the event flags. */ + status = tx_event_flags_get(group_ptr, requested_flags, get_option, &local_actual_flags_ptr, wait_option); + + /* Update the actual flags. */ + *actual_flags_ptr = local_actual_flags_ptr; + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_event_flags_set.c b/common/core/src/ux_utility_event_flags_set.c new file mode 100644 index 0000000..4c01799 --- /dev/null +++ b/common/core/src/ux_utility_event_flags_set.c @@ -0,0 +1,83 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_event_flags_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function set event flags from event flag group */ +/* */ +/* INPUT */ +/* */ +/* group_ptr Event flag control group */ +/* flags_to_set 32 bits variable event flags */ +/* set_option set option */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_event_flags_set ThreadX set event flag */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, + UINT set_option) +{ + +UINT status; + + /* Call ThreadX to set the event flags. */ + status = tx_event_flags_set(group_ptr, flags_to_set, set_option); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_long_get.c b/common/core/src/ux_utility_long_get.c new file mode 100644 index 0000000..46b4053 --- /dev/null +++ b/common/core/src/ux_utility_long_get.c @@ -0,0 +1,84 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_long_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads a 32-bit value. */ +/* */ +/* INPUT */ +/* */ +/* address Source address */ +/* */ +/* OUTPUT */ +/* */ +/* 32-bit value */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_utility_long_get(UCHAR * address) +{ + +ULONG value; + + + /* In order to make this function endian agnostic and memory alignment + independent, we read a byte at a time from the address. */ + value = (ULONG) *address++; + value |= (ULONG)*address++ << 8; + value |= (ULONG)*address++ << 16; + value |= (ULONG)*address << 24; + + /* Return 32-bit value. */ + return(value); +} + diff --git a/common/core/src/ux_utility_long_get_big_endian.c b/common/core/src/ux_utility_long_get_big_endian.c new file mode 100644 index 0000000..96b59fc --- /dev/null +++ b/common/core/src/ux_utility_long_get_big_endian.c @@ -0,0 +1,83 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_long_get_big_endian PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads a 32-bit value in big endian format. */ +/* */ +/* INPUT */ +/* */ +/* address Source address */ +/* */ +/* OUTPUT */ +/* */ +/* 16-bit value */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_utility_long_get_big_endian(UCHAR * address) +{ + +ULONG value; + + + /* We read a byte at a time from the address. */ + value = (ULONG) ((*address++) << 24); + value |= (ULONG) ((*address++) << 16); + value |= (ULONG) ((*address++) << 8); + value |= (ULONG) *address; + + /* Return 32-bit value. */ + return(value); +} + diff --git a/common/core/src/ux_utility_long_put.c b/common/core/src/ux_utility_long_put.c new file mode 100644 index 0000000..b68b441 --- /dev/null +++ b/common/core/src/ux_utility_long_put.c @@ -0,0 +1,82 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_long_put PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a 32-bit value. */ +/* */ +/* INPUT */ +/* */ +/* address Destination address */ +/* value 32-bit value */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_long_put(UCHAR * address, ULONG value) +{ + + /* In order to make this function endian agnostic and memory alignment + independent, we write a byte at a time from the address. */ + *address++ = (UCHAR) (value & 0xff); + *address++ = (UCHAR) ((value >> 8) & 0xff); + *address++ = (UCHAR) ((value >> 16) & 0xff); + *address = (UCHAR) ((value >> 24) & 0xff); + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_utility_long_put_big_endian.c b/common/core/src/ux_utility_long_put_big_endian.c new file mode 100644 index 0000000..a7e6244 --- /dev/null +++ b/common/core/src/ux_utility_long_put_big_endian.c @@ -0,0 +1,90 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_long_put_big_endian PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a 32-bit value in big endian format. */ +/* */ +/* INPUT */ +/* */ +/* address Destination address */ +/* value 32-bit value */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_long_put_big_endian(UCHAR * address, ULONG value) +{ + +ULONG low_word_value; +ULONG high_word_value; + + /* First we swap the value words. */ + low_word_value = value >> 16; + high_word_value = value << 16; + value = high_word_value | low_word_value; + + /* In order to make this function endian agnostic and memory alignment + independent, we write a byte at a time from the address. */ + *address++ = (UCHAR) ((value >> 8) & 0xff); + *address++ = (UCHAR) (value & 0xff); + *address++ = (UCHAR) ((value >> 24 ) & 0xff); + *address = (UCHAR) ((value >> 16) & 0xff); + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_utility_memory_allocate.c b/common/core/src/ux_utility_memory_allocate.c new file mode 100644 index 0000000..c874fb6 --- /dev/null +++ b/common/core/src/ux_utility_memory_allocate.c @@ -0,0 +1,354 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_memory_allocate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates a block of memory for the specified size */ +/* and alignment. */ +/* */ +/* INPUT */ +/* */ +/* memory_alignment Memory alignment required */ +/* memory_cache_flag Memory pool source */ +/* memory_size_requested Number of bytes required */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to block of memory */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_free_block_best_get Get best fit block of memory */ +/* _ux_utility_memory_set Set block of memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID *_ux_utility_memory_allocate(ULONG memory_alignment, ULONG memory_cache_flag, + ULONG memory_size_requested) +{ + +UX_MEMORY_BLOCK *memory_block; +UX_MEMORY_BLOCK *new_memory_block; +UX_MEMORY_BLOCK *leftover_memory_block; +ULONG memory_for_alignment; +ULONG memory_removed_from_pool; +ULONG leftover; +UCHAR *memory_buffer; +ALIGN_TYPE int_memory_buffer; + + + /* Get the mutex as this is a critical section. */ + _ux_utility_mutex_on(&_ux_system -> ux_system_mutex); + +#ifdef UX_ENFORCE_SAFE_ALIGNMENT + + /* Check if safe alignment requested, in this case switch to UX_NO_ALIGN. */ + if (memory_alignment == UX_SAFE_ALIGN) + { + + /* We will use the memory_size_requested for the alignment. + But we check to see if we have a minimum or maximum alignment. */ + if (memory_size_requested < UX_ALIGN_MIN) + + /* No need to bother about alignment for small packets sizes. */ + memory_alignment = UX_NO_ALIGN; + + else + { + + /* Check if we are over the maximum. */ + if (memory_size_requested > UX_MAX_SCATTER_GATHER_ALIGNMENT) + + /* We are over the max alignment required. Use the maximum instead. */ + memory_alignment = UX_MAX_SCATTER_GATHER_ALIGNMENT - 1; + + else + { + /* We are not over the maximum, so approximate the alignment according to the size of the memory. + Check range for alignment on 4096 bytes. */ + if (memory_size_requested >= UX_ALIGN_2048 + 1) + memory_alignment = UX_ALIGN_4096; + + else + { + + /* Check range for alignment on 2048 bytes. */ + if (memory_size_requested >= UX_ALIGN_1024 + 1) + memory_alignment = UX_ALIGN_2048; + + else + { + + /* Check range for alignment on 1024 bytes. */ + if (memory_size_requested >= UX_ALIGN_512 + 1) + memory_alignment = UX_ALIGN_1024; + + else + { + + /* Check range for alignment on 512 bytes. */ + if (memory_size_requested >= UX_ALIGN_256 + 1) + memory_alignment = UX_ALIGN_512; + + else + { + + /* Check range for alignment on 256 bytes. */ + if (memory_size_requested >= UX_ALIGN_128 + 1) + memory_alignment = UX_ALIGN_256; + + else + { + + /* Check range for alignment on 128 bytes. */ + if (memory_size_requested >= UX_ALIGN_64 + 1) + memory_alignment = UX_ALIGN_128; + + else + { + + /* Check range for alignment on 128 bytes. */ + if (memory_size_requested >= UX_ALIGN_64 + 1) + memory_alignment = UX_ALIGN_128; + + else + { + + /* Check range for alignment on 64 bytes. */ + if (memory_size_requested >= UX_ALIGN_32 + 1) + memory_alignment = UX_ALIGN_64; + + else + { + + /* Check range for alignment on 32 bytes. */ + if (memory_size_requested >= UX_ALIGN_16 + 1) + memory_alignment = UX_ALIGN_32; + + else + memory_alignment = UX_ALIGN_MIN; + + + } + } + } + } + } + } + } + } + } + } + } + +#else + + /* Check if safe alignment requested, in this case switch to UX_NO_ALIGN. */ + if (memory_alignment == UX_SAFE_ALIGN) + memory_alignment = UX_NO_ALIGN; + +#endif + + /* Ensure the alignment meats the minimum. */ + if (memory_alignment < UX_ALIGN_MIN) + memory_alignment = UX_ALIGN_MIN; + + /* Adjust the memory alignment since our macros are one minus the desired alignment. + Also determine the amount of extra memory we need for the alignment, which is one + minus the actual alignment. */ + memory_for_alignment = memory_alignment; + memory_alignment++; + + /* We need to make sure that the next memory block buffer is 16-byte aligned too. We + do this by first adjusting the requested memory to be 16-byte aligned. One problem + now is that the memory block might not be a size that is a multiple of 16, so we need + to add the amount of memory required such that the memory buffer after the block has + the correct alignment. For example, if the memory block has a size of 24, then we need + to make sure it is placed on an 8-byte alignment that is after a 16-byte alignment so + that the memory right after the memory block is 16-byte aligned (8 + 24 = 32). */ + memory_size_requested = (memory_size_requested + UX_ALIGN_MIN) & (~(ULONG)UX_ALIGN_MIN); + memory_size_requested += (((ULONG)sizeof(UX_MEMORY_BLOCK) + UX_ALIGN_MIN) & (~(ULONG)UX_ALIGN_MIN)) - (ULONG)sizeof(UX_MEMORY_BLOCK); + + /* Try to find the best block for this memory by requesting the maximum amount of + memory we'll need which is calculated as follows: the amount memory requested by + the caller plus the maximum amount of memory wasted due to alignment plus 2 memory + blocks structs - one for the new memory block we'll create for the user block and one + that we might create if there is extra memory after doing the alignment. */ + memory_block = _ux_utility_memory_free_block_best_get(memory_cache_flag, memory_size_requested + memory_for_alignment + (ULONG)sizeof(UX_MEMORY_BLOCK)); + + /* If the block returned is NULL, there is no free memory in the pool + for that size. */ + if (memory_block == UX_NULL) + { + + /* Release the protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, memory_size_requested, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, UX_MEMORY_INSUFFICIENT); + + /* Return NULL to indicate no block was found. */ + return(UX_NULL); + } + + /* Get the memory buffer for this block. */ + int_memory_buffer = (ALIGN_TYPE) ((UCHAR *) memory_block + sizeof(UX_MEMORY_BLOCK)); + + /* Are we already aligned? */ + if ((int_memory_buffer & (memory_alignment - 1)) == 0) + { + + /* Setup the new memory block. */ + new_memory_block = (UX_MEMORY_BLOCK *) ((UCHAR *) memory_block + sizeof(UX_MEMORY_BLOCK) + memory_size_requested); + new_memory_block -> ux_memory_block_next = memory_block -> ux_memory_block_next; + new_memory_block -> ux_memory_block_previous = memory_block; + new_memory_block -> ux_memory_block_size = memory_block -> ux_memory_block_size - memory_size_requested - (ULONG)sizeof(UX_MEMORY_BLOCK); + new_memory_block -> ux_memory_block_status = UX_MEMORY_UNUSED; + + /* Update the current memory block. */ + memory_block -> ux_memory_block_size = memory_size_requested; + memory_block -> ux_memory_block_next = new_memory_block; + memory_block -> ux_memory_block_status = UX_MEMORY_USED; + + /* Declare how much memory we removed from the pool. */ + memory_removed_from_pool = memory_block -> ux_memory_block_size + (ULONG)sizeof(UX_MEMORY_BLOCK); + } + else + { + + /* Align the buffer. The first thing we do is increment by the size of a + memory block because we have to make sure we have enough memory for at + least that. */ + int_memory_buffer += (ULONG)sizeof(UX_MEMORY_BLOCK); + int_memory_buffer += memory_alignment - 1; + int_memory_buffer &= ~(((ALIGN_TYPE) memory_alignment) - 1); + + /* Setup the new memory block. Note that its size is updated again later. */ + new_memory_block = (UX_MEMORY_BLOCK *) (int_memory_buffer - (ULONG)sizeof(UX_MEMORY_BLOCK)); + new_memory_block -> ux_memory_block_previous = memory_block; + new_memory_block -> ux_memory_block_next = memory_block -> ux_memory_block_next; + new_memory_block -> ux_memory_block_size = memory_block -> ux_memory_block_size; + new_memory_block -> ux_memory_block_status = UX_MEMORY_USED; + + /* Update the current memory block. */ + int_memory_buffer = (ALIGN_TYPE) ((UCHAR *) memory_block + sizeof(UX_MEMORY_BLOCK)); + memory_block -> ux_memory_block_next = new_memory_block; + memory_block -> ux_memory_block_size = (ULONG) ((ALIGN_TYPE) new_memory_block - int_memory_buffer); + + /* Update the new memory block's size. */ + new_memory_block -> ux_memory_block_size -= (memory_block -> ux_memory_block_size + (ULONG)sizeof(UX_MEMORY_BLOCK)); + + /* Calculate how much memory is leftover in the new memory block after doing + the alignment. */ + leftover = new_memory_block -> ux_memory_block_size - memory_size_requested; + + /* Can we fit another block after the new block? */ + if (leftover > sizeof(UX_MEMORY_BLOCK)) + { + + /* Setup the leftover memory block. */ + leftover_memory_block = (UX_MEMORY_BLOCK *) ((ALIGN_TYPE) new_memory_block + sizeof(UX_MEMORY_BLOCK) + memory_size_requested); + leftover_memory_block -> ux_memory_block_next = new_memory_block -> ux_memory_block_next; + leftover_memory_block -> ux_memory_block_previous = new_memory_block; + leftover_memory_block -> ux_memory_block_size = leftover - (ULONG)sizeof(UX_MEMORY_BLOCK); + leftover_memory_block -> ux_memory_block_status = UX_MEMORY_UNUSED; + + new_memory_block -> ux_memory_block_next = leftover_memory_block; + new_memory_block -> ux_memory_block_size -= leftover; + } + + /* Declare how much memory we removed from the pool. */ + memory_removed_from_pool = new_memory_block -> ux_memory_block_size + (ULONG)sizeof(UX_MEMORY_BLOCK); + + /* The new memory block is the one we give to the user. */ + memory_block = new_memory_block; + } + + /* The memory to be returned is after the block header. */ + memory_buffer = ((UCHAR *) memory_block) + sizeof(UX_MEMORY_BLOCK); + + /* Clear the memory block. */ + _ux_utility_memory_set(memory_buffer, 0, memory_size_requested); + + /* Update the memory free in the pool. */ + if (_ux_system -> ux_system_cache_safe_memory_pool_start == _ux_system -> ux_system_regular_memory_pool_start) + { + + /* There is only one memory pool. */ + _ux_system -> ux_system_regular_memory_pool_free -= memory_removed_from_pool; + } + else + { + + switch (memory_cache_flag) + { + + case UX_CACHE_SAFE_MEMORY: + /* Update the amount of free memory in the cache safe memory pool. */ + _ux_system -> ux_system_cache_safe_memory_pool_free -= memory_removed_from_pool; + break; + + default: + /* Update the amount of free memory in the regular memory pool. */ + _ux_system -> ux_system_regular_memory_pool_free -= memory_removed_from_pool; + break; + + } + } + + /* Release the protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* The memory block pointer contains a memory area properly + aligned. */ + return(memory_buffer); +} diff --git a/common/core/src/ux_utility_memory_allocate_add_safe.c b/common/core/src/ux_utility_memory_allocate_add_safe.c new file mode 100644 index 0000000..9a972d5 --- /dev/null +++ b/common/core/src/ux_utility_memory_allocate_add_safe.c @@ -0,0 +1,76 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_memory_allocate_add_safe PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates a block of memory for the specified added */ +/* size and alignment. */ +/* */ +/* Note if adding result overflow, no memory is allocated. */ +/* */ +/* INPUT */ +/* */ +/* align Memory alignment required */ +/* cache Memory pool source */ +/* size_add_a Number of bytes a to add */ +/* size_add_b Number of bytes b to add */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to block of memory */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate block of memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID* _ux_utility_memory_allocate_add_safe(ULONG align,ULONG cache,ULONG size_add_a,ULONG size_add_b) +{ + return UX_UTILITY_MEMORY_ALLOCATE_ADD_SAFE(align, cache, size_add_a, size_add_b); +} diff --git a/common/core/src/ux_utility_memory_allocate_mulc_safe.c b/common/core/src/ux_utility_memory_allocate_mulc_safe.c new file mode 100644 index 0000000..000a465 --- /dev/null +++ b/common/core/src/ux_utility_memory_allocate_mulc_safe.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_memory_allocate_mulc_safe PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates a block of memory for the specified */ +/* multiplied size and alignment. */ +/* */ +/* Note if multiplying result overflow, no memory is allocated. */ +/* Note it's assumed at least the last factor to multiply is const for */ +/* possible code optimization. */ +/* */ +/* INPUT */ +/* */ +/* align Memory alignment required */ +/* cache Memory pool source */ +/* size_mul_v Number of bytes variable to */ +/* multiply */ +/* size_mul_c Number of bytes const to */ +/* multiply */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to block of memory */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate block of memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID* _ux_utility_memory_allocate_mulc_safe(ULONG align,ULONG cache,ULONG size_mul_v,ULONG size_mul_c) +{ + return UX_UTILITY_MEMORY_ALLOCATE_MULC_SAFE(align, cache, size_mul_v, size_mul_c); +} diff --git a/common/core/src/ux_utility_memory_allocate_mulv_safe.c b/common/core/src/ux_utility_memory_allocate_mulv_safe.c new file mode 100644 index 0000000..6054ef7 --- /dev/null +++ b/common/core/src/ux_utility_memory_allocate_mulv_safe.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_memory_allocate_mulv_safe PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates a block of memory for the specified */ +/* multiplied size and alignment. */ +/* */ +/* Note if multiplying result overflow, no memory is allocated. */ +/* Note it's assumed all factors to multiply is variables for */ +/* possible code optimization. */ +/* */ +/* INPUT */ +/* */ +/* align Memory alignment required */ +/* cache Memory pool source */ +/* size_mul_v0 Number of bytes variable to */ +/* multiply */ +/* size_mul_v1 Number of bytes variable to */ +/* multiply */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to block of memory */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate block of memory */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID* _ux_utility_memory_allocate_mulv_safe(ULONG align,ULONG cache,ULONG size_mul_v0,ULONG size_mul_v1) +{ + return UX_UTILITY_MEMORY_ALLOCATE_MULV_SAFE(align, cache, size_mul_v0, size_mul_v1); +} diff --git a/common/core/src/ux_utility_memory_compare.c b/common/core/src/ux_utility_memory_compare.c new file mode 100644 index 0000000..713e11e --- /dev/null +++ b/common/core/src/ux_utility_memory_compare.c @@ -0,0 +1,98 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_memory_compare PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function compares two memory blocks. */ +/* */ +/* INPUT */ +/* */ +/* memory_source Pointer to source */ +/* memory_destination Pointer to destination */ +/* length Number of bytes to compare */ +/* */ +/* OUTPUT */ +/* */ +/* UX_SUCCESS If blocks are equal */ +/* UX_ERROR If blocks are not equal */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_memory_compare(VOID *memory_source, VOID *memory_destination, ULONG length) +{ + +UCHAR * source; +UCHAR * destination; + + + /* Setup source and destination byte oriented pointers. */ + source = (UCHAR *) memory_source; + destination = (UCHAR *) memory_destination; + + /* Loop to compare blocks. */ + while(length--) + { + + /* Compare a single byte. */ + if(*destination++ != *source++) + { + + /* Not equal, return an error. */ + return(UX_ERROR); + } + } + + /* Blocks are equal, return success. */ + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_utility_memory_copy.c b/common/core/src/ux_utility_memory_copy.c new file mode 100644 index 0000000..0bb83d0 --- /dev/null +++ b/common/core/src/ux_utility_memory_copy.c @@ -0,0 +1,92 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_memory_copy PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function copies a block of memory from a source to a */ +/* destination. */ +/* */ +/* INPUT */ +/* */ +/* memory_destination Pointer to destination */ +/* memory_source Pointer to source */ +/* length Number of bytes to copy */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_memory_copy(VOID *memory_destination, VOID *memory_source, ULONG length) +{ + +UCHAR * source; +UCHAR * destination; + + /* Setup byte oriented source and destination pointers. */ + source = (UCHAR *) memory_source; + destination = (UCHAR *) memory_destination; + + /* Loop to perform the copy. */ + while(length--) + { + + /* Copy one byte. */ + *destination++ = *source++; + } + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_utility_memory_free.c b/common/core/src/ux_utility_memory_free.c new file mode 100644 index 0000000..02d28f6 --- /dev/null +++ b/common/core/src/ux_utility_memory_free.c @@ -0,0 +1,182 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_memory_free PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function frees a previously allocated memory block. */ +/* */ +/* INPUT */ +/* */ +/* memory Pointer to memory block */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_mutex_on Start system protection */ +/* _ux_utility_mutex_off End system protection */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_memory_free(VOID *memory) +{ + +UX_MEMORY_BLOCK *memory_block; +UX_MEMORY_BLOCK *next_block; +ULONG memory_size_returned; +UCHAR *memory_address; + + /* Get the mutex as this is a critical section. */ + _ux_utility_mutex_on(&_ux_system -> ux_system_mutex); + + /* The memory block for this memory pointer is located right before the + memory. */ + memory_block = (UX_MEMORY_BLOCK *) (((UCHAR *) memory) - sizeof(UX_MEMORY_BLOCK)); + + /* Keep track of the memory returned to the pool. */ + memory_size_returned = memory_block -> ux_memory_block_size + (ULONG)sizeof(UX_MEMORY_BLOCK); + + /* Check this memory block to see if it valid. */ + if (memory_block -> ux_memory_block_status != UX_MEMORY_USED) + { + + /* Not valid. Release the protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, UX_MEMORY_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_CORRUPTED, memory, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return to caller. */ + return; + } + + /* We mark this memory block as being unused. */ + memory_block -> ux_memory_block_status = UX_MEMORY_UNUSED; + + /* Now we must concatenate as many free blocks as possible, + that include the blocks before and the blocks after the current + block. Scan memory backwards. */ + + while (memory_block -> ux_memory_block_previous !=UX_NULL) + { + + /* Check if the block is free. */ + if (memory_block -> ux_memory_block_previous -> ux_memory_block_status == UX_MEMORY_UNUSED) + + /* The memory block before is free. This will be our starting point to + concatenate memory. */ + memory_block = memory_block -> ux_memory_block_previous; + + else + + /* The previous memory block is not free. */ + break; + } + + /* The pointer to the memory block is now our first free block. We use this + starting address to concatenate all the contiguous memory block. */ + next_block = memory_block -> ux_memory_block_next; + while (next_block != UX_NULL) + { + + /* Determine if the memory block is used. */ + if (next_block -> ux_memory_block_status == UX_MEMORY_USED) + { + + /* Yes, move to next block. */ + memory_block -> ux_memory_block_next = next_block; + next_block -> ux_memory_block_previous = memory_block; + break; + } + + memory_block -> ux_memory_block_next = next_block -> ux_memory_block_next; + memory_block -> ux_memory_block_size += next_block -> ux_memory_block_size + (ULONG)sizeof(UX_MEMORY_BLOCK); + next_block = next_block -> ux_memory_block_next; + } + + /* Update the memory free in the appropriate pool. We need to know if this + block is in regular memory or cache safe memory. */ + if(_ux_system -> ux_system_cache_safe_memory_pool_start == _ux_system -> ux_system_regular_memory_pool_start) + { + + /* There is only one regular memory pool. */ + _ux_system -> ux_system_regular_memory_pool_free += memory_size_returned; + + } + else + { + + /* Which pool is this memory in ? */ + memory_address = (UCHAR *) _ux_system -> ux_system_regular_memory_pool_start; + + /* If the memory address is in this range, we are in the regular memory pool. */ + if ((UCHAR *) memory_block >= memory_address && (UCHAR *) memory_block < (memory_address + _ux_system -> ux_system_regular_memory_pool_size)) + + /* Update the regular memory pool. */ + _ux_system -> ux_system_regular_memory_pool_free += memory_size_returned; + + else + + /* Update the cache safe memory pool. */ + _ux_system -> ux_system_cache_safe_memory_pool_free += memory_size_returned; + + } + + /* Release the protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_utility_memory_free_block_best_get.c b/common/core/src/ux_utility_memory_free_block_best_get.c new file mode 100644 index 0000000..b6294bb --- /dev/null +++ b/common/core/src/ux_utility_memory_free_block_best_get.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** USBX main stack */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_memory_free_block_best_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the best free memory block. */ +/* */ +/* INPUT */ +/* */ +/* memory_cache_flag Memory pool source */ +/* memory_size_requested Size of memory requested */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to best free block */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_MEMORY_BLOCK *_ux_utility_memory_free_block_best_get(ULONG memory_cache_flag, + ULONG memory_size_requested) +{ + +UX_MEMORY_BLOCK *memory_block; +UX_MEMORY_BLOCK *best_memory_block; + + + /* Reset the free memory block. */ + best_memory_block = UX_NULL; + + /* Check the type of memory we need. */ + switch (memory_cache_flag) + { + + case UX_REGULAR_MEMORY : + + /* Start at the beginning of the regular memory pool. */ + memory_block = _ux_system -> ux_system_regular_memory_pool_start; + break; + + case UX_CACHE_SAFE_MEMORY : + + /* Start at the beginning of the cache safe memory pool. */ + memory_block = _ux_system -> ux_system_cache_safe_memory_pool_start; + break; + + default : + + /* Wrong memory type. */ + return(UX_NULL); + + } + + /* Loop on all memory blocks from the beginning. */ + while (memory_block != UX_NULL) + { + + /* Check the memory block status. */ + if (memory_block -> ux_memory_block_status == UX_MEMORY_UNUSED) + { + + /* Check the size of this free block and see if it will + fit the memory requirement. */ + if (memory_block -> ux_memory_block_size > memory_size_requested) + { + + /* This memory block will do. Now see if it is the best. + The best memory block is the one whose memory is closest + to the memory requested. */ + if (best_memory_block == UX_NULL) + + /* Initialize the best block with the first free one. */ + best_memory_block = memory_block; + else + { + + if (memory_block -> ux_memory_block_size < best_memory_block -> ux_memory_block_size) + + /* We have discovered a better fit block. */ + best_memory_block = memory_block; + } + } + } + + /* Search the next free block until the end. */ + memory_block = memory_block -> ux_memory_block_next; + } + + /* If no free memory block was found, the return value will be NULL. */ + return(best_memory_block); +} + diff --git a/common/core/src/ux_utility_memory_set.c b/common/core/src/ux_utility_memory_set.c new file mode 100644 index 0000000..5cf7a7f --- /dev/null +++ b/common/core/src/ux_utility_memory_set.c @@ -0,0 +1,90 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_memory_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets a memory block with a specific value. */ +/* */ +/* INPUT */ +/* */ +/* destination Destination address */ +/* value 8-bit value */ +/* length Size of memory to set */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_memory_set(VOID *destination, UCHAR value, ULONG length) +{ + +UCHAR * work_ptr; + + + /* Setup the working pointer */ + work_ptr = (UCHAR *) destination; + + /* Loop to set the memory. */ + while(length--) + { + + /* Set a byte. */ + *work_ptr++ = value; + } + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_utility_mutex_create.c b/common/core/src/ux_utility_mutex_create.c new file mode 100644 index 0000000..b8bb410 --- /dev/null +++ b/common/core/src/ux_utility_mutex_create.c @@ -0,0 +1,92 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_mutex_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a protection mutex. */ +/* */ +/* INPUT */ +/* */ +/* mutex Pointer to mutex */ +/* mutex_name Name of mutex */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_create ThreadX mutex create */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_mutex_create(TX_MUTEX *mutex, CHAR *mutex_name) +{ + +UINT status; + + + /* Call ThreadX to create the Mutex object. */ + status = tx_mutex_create(mutex, (CHAR *) mutex_name, TX_NO_INHERIT); + + /* Check for status. */ + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, status); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MUTEX_ERROR, mutex, 0, 0, UX_TRACE_ERRORS, 0, 0) + + } + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_mutex_delete.c b/common/core/src/ux_utility_mutex_delete.c new file mode 100644 index 0000000..caed65c --- /dev/null +++ b/common/core/src/ux_utility_mutex_delete.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_mutex_delete PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes a protection mutex. */ +/* */ +/* INPUT */ +/* */ +/* mutex Pointer to mutex */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_create ThreadX mutex create */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_mutex_delete(TX_MUTEX *mutex) +{ + +UINT status; + + + /* Call ThreadX to delete the Mutex object. */ + status = tx_mutex_delete(mutex); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_mutex_off.c b/common/core/src/ux_utility_mutex_off.c new file mode 100644 index 0000000..03ccec2 --- /dev/null +++ b/common/core/src/ux_utility_mutex_off.c @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_mutex_off PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function releases system protection. */ +/* */ +/* INPUT */ +/* */ +/* Mutex */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_put ThreadX mutex put */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_mutex_off(TX_MUTEX *mutex) +{ + + /* Call ThreadX to release protection. */ + tx_mutex_put(mutex); + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_utility_mutex_on.c b/common/core/src/ux_utility_mutex_on.c new file mode 100644 index 0000000..14a4aa2 --- /dev/null +++ b/common/core/src/ux_utility_mutex_on.c @@ -0,0 +1,87 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_mutex_on PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets system protection. */ +/* */ +/* INPUT */ +/* */ +/* Mutex */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get ThreadX mutex get */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_mutex_on(TX_MUTEX *mutex) +{ + +UINT status; + + /* Call ThreadX to get system mutex. */ + status = tx_mutex_get(mutex, TX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, status); + } + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_utility_pci_class_scan.c b/common/core/src/ux_utility_pci_class_scan.c new file mode 100644 index 0000000..672fada --- /dev/null +++ b/common/core/src/ux_utility_pci_class_scan.c @@ -0,0 +1,130 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_pci_class_scan PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function scans the PCI bus from a certain position for a */ +/* specific PCI class. */ +/* */ +/* INPUT */ +/* */ +/* pci_class PCI class requested */ +/* bus_number PCI bus number */ +/* device_number Device number */ +/* function_number Function number */ +/* current_bus_number Current bus number */ +/* current_device_number Current device number */ +/* current_function_number Current function number */ +/* */ +/* OUTPUT */ +/* */ +/* 32-bit value */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_pci_read PCI read utility */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_utility_pci_class_scan(ULONG pci_class, ULONG bus_number, ULONG device_number, + ULONG function_number, ULONG *current_bus_number, + ULONG *current_device_number, ULONG *current_function_number) +{ + +ULONG bus_number_index; +ULONG device_number_index; +ULONG function_number_index; +ULONG value; +ULONG current_pci_class; + + + /* Scan all bus. */ + for (bus_number_index = bus_number; bus_number_index <= UX_PCI_NB_BUS; bus_number_index++) + { + + /* Scan all devices. */ + for(device_number_index = device_number;device_number_index <= UX_PCI_NB_DEVICE; device_number_index++) + { + + /* Scan all functions. */ + for(function_number_index = function_number; function_number_index <= UX_PCI_NB_FUNCTIONS; function_number_index++) + { + + /* Reset all PCI address for next loop. */ + function_number = 0; + device_number = 0; + bus_number = 0; + + /* Read the PCI class bus/device/function. */ + value = _ux_utility_pci_read(bus_number_index, device_number_index, function_number_index, + UX_PCI_CFG_REVISION,32); + + /* Isolate the class code which is in the upper 3 bytes. */ + current_pci_class = (value >> 8) & 0x00ffffff; + + /* Do we have a match with the demanded class? */ + if(current_pci_class == pci_class) + { + + /* Return the position of this device on the PCI */ + *current_bus_number = bus_number_index; + *current_device_number = device_number_index; + *current_function_number = function_number_index; + + /* Return success! */ + return(UX_SUCCESS); + } + } + } + } + + /* Return an error since we didn't find anything. */ + return(UX_ERROR); +} + diff --git a/common/core/src/ux_utility_pci_read.c b/common/core/src/ux_utility_pci_read.c new file mode 100644 index 0000000..22cd473 --- /dev/null +++ b/common/core/src/ux_utility_pci_read.c @@ -0,0 +1,123 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_pci_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads a 32/16/8 bit value from a specific PCI bus */ +/* at a certain offset. */ +/* */ +/* INPUT */ +/* */ +/* bus_number PCI bus number */ +/* device_number Device number */ +/* function_number Function number */ +/* offset Offset */ +/* read_size Size of read */ +/* */ +/* OUTPUT */ +/* */ +/* 32-bit value */ +/* */ +/* CALLS */ +/* */ +/* inpl PCI input long */ +/* inpw PCI input word */ +/* inpb PCI input byte */ +/* outpl PCI output function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_utility_pci_read(ULONG bus_number, ULONG device_number, ULONG function_number, + ULONG offset, UINT read_size) +{ + +ULONG destination_address; +ULONG cfg_ctrl; + + + /* Calculate the destination address. */ + destination_address = (((bus_number << 16) & 0x00ff0000) | ((device_number << 11) & 0x0000f800) | + ((function_number << 8) & 0x00000700)); + + /* Calculate the configure control value. */ + cfg_ctrl = destination_address | offset | 0x80000000; + + /* Read based on the size requested. */ + switch(read_size) + { + + case 32: + + /* Write the address we need to read from. */ + outpl(UX_PCI_CFG_CTRL_ADDRESS, cfg_ctrl); + + /* Return the 32 bit content of this address. */ + return(inpl(UX_PCI_CFG_DATA_ADDRESS)); + + case 16: + + /* Write the address we need to read from. */ + outpl(UX_PCI_CFG_CTRL_ADDRESS, cfg_ctrl); + + /* Return the 16 bit content of this address. */ + return((USHORT)(inpw(UX_PCI_CFG_DATA_ADDRESS))); + + case 8: + + /* Write the address we need to read from. */ + outpl(UX_PCI_CFG_CTRL_ADDRESS, cfg_ctrl); + + /* Return the 8 bit content of this address */ + return((ULONG)(inpb(UX_PCI_CFG_DATA_ADDRESS))); + + default: + + return(0); + } +} diff --git a/common/core/src/ux_utility_pci_write.c b/common/core/src/ux_utility_pci_write.c new file mode 100644 index 0000000..a17655d --- /dev/null +++ b/common/core/src/ux_utility_pci_write.c @@ -0,0 +1,127 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_pci_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a 32/16/8 bit value to a specific PCI bus */ +/* at a certain offset. */ +/* */ +/* INPUT */ +/* */ +/* bus_number PCI bus number */ +/* device_number Device number */ +/* function_number Function number */ +/* offset Offset */ +/* value Value to write */ +/* write_size Size of write */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* outpl PCI output long function */ +/* outpw PCI output word function */ +/* outpb PCI output byte function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_pci_write(ULONG bus_number, ULONG device_number, ULONG function_number, + ULONG offset, ULONG value, UINT write_size) +{ + +ULONG destination_address; +ULONG cfg_ctrl; + + + /* Calculate the destination address. */ + destination_address = (((bus_number << 16) & 0x00ff0000) | ((device_number << 11) & 0x0000f800) | + ((function_number << 8) & 0x00000700)); + + /* Calculate the configure control value. */ + cfg_ctrl = destination_address | offset | 0x80000000; + + /* Process relative to write size. */ + switch(write_size) + { + + case 32: + + /* Write the address we need to write to. */ + outpl(UX_PCI_CFG_CTRL_ADDRESS, cfg_ctrl); + + /* Write the 32 bit content of this address. */ + outpl(UX_PCI_CFG_DATA_ADDRESS, value); + break; + + case 16: + + /* Write the address we need to write to. */ + outpl(UX_PCI_CFG_CTRL_ADDRESS, cfg_ctrl); + + /* Write the 16 bit content of this address. */ + outpw(UX_PCI_CFG_DATA_ADDRESS + (offset & 2), (USHORT) value); + break; + + case 8: + + /* Write the address we need to write to. */ + outpl(UX_PCI_CFG_CTRL_ADDRESS, cfg_ctrl); + + /* Write the 8 bit content of this address */ + outpb(UX_PCI_CFG_DATA_ADDRESS + (offset & 3), (UCHAR) value); + break; + + default: + + break; + } +} + diff --git a/common/core/src/ux_utility_physical_address.c b/common/core/src/ux_utility_physical_address.c new file mode 100644 index 0000000..8709155 --- /dev/null +++ b/common/core/src/ux_utility_physical_address.c @@ -0,0 +1,82 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_physical_address PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns a physical address given the supplied */ +/* virtual address. */ +/* */ +/* INPUT */ +/* */ +/* virtual_address Physical address */ +/* */ +/* OUTPUT */ +/* */ +/* physical_address Virtual address */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID *_ux_utility_physical_address(VOID *virtual_address) +{ + +VOID *physical_address; + + /* Any code to translate the virtual address into a physical address + will be below. If there is no translation, the physical address= + the virtual address. */ + + physical_address = virtual_address; + + return(physical_address); +} + diff --git a/common/core/src/ux_utility_semaphore_create.c b/common/core/src/ux_utility_semaphore_create.c new file mode 100644 index 0000000..ec411fa --- /dev/null +++ b/common/core/src/ux_utility_semaphore_create.c @@ -0,0 +1,93 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_semaphore_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a semaphore. */ +/* */ +/* INPUT */ +/* */ +/* semaphore Semaphore to create */ +/* semaphore_name Semaphore name */ +/* initial_count Initial semaphore count */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_semaphore_create ThreadX semaphore create */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_semaphore_create(TX_SEMAPHORE *semaphore, CHAR *semaphore_name, UINT initial_count) +{ + +UINT status; + + /* Call ThreadX to create the semaphore. */ + status = tx_semaphore_create(semaphore, (CHAR *) semaphore_name, initial_count); + + /* Check for status. */ + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, status); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_SEMAPHORE_ERROR, semaphore, 0, 0, UX_TRACE_ERRORS, 0, 0) + + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_semaphore_delete.c b/common/core/src/ux_utility_semaphore_delete.c new file mode 100644 index 0000000..d9d3ea5 --- /dev/null +++ b/common/core/src/ux_utility_semaphore_delete.c @@ -0,0 +1,79 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_semaphore_delete PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes the specified semaphore. */ +/* */ +/* INPUT */ +/* */ +/* semaphore Semaphore to delete */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_semaphore_delete ThreadX semaphore delete */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_semaphore_delete(TX_SEMAPHORE *semaphore) +{ + +UINT status; + + /* Call ThreadX Semaphore delete function. */ + status = tx_semaphore_delete(semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_semaphore_get.c b/common/core/src/ux_utility_semaphore_get.c new file mode 100644 index 0000000..8627b5d --- /dev/null +++ b/common/core/src/ux_utility_semaphore_get.c @@ -0,0 +1,107 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_semaphore_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets a semaphore signal. */ +/* */ +/* INPUT */ +/* */ +/* semaphore Semaphore to get signal from */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_identify ThreadX identify thread */ +/* tx_thread_info_get ThreadX get thread info */ +/* tx_semaphore_get ThreadX semaphore get */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_semaphore_get(TX_SEMAPHORE *semaphore, ULONG semaphore_signal) +{ + +UINT status; +TX_THREAD *my_thread; +CHAR *name; +UINT state; +ULONG run_count; +UINT priority; +UINT preemption_threshold; +ULONG time_slice; +TX_THREAD *next_thread; +TX_THREAD *suspended_thread; + + /* Call TX to know my own tread. */ + my_thread = tx_thread_identify(); + + /* Retrieve information about the previously created thread "my_thread." */ + tx_thread_info_get(my_thread, &name, &state, &run_count, + &priority, &preemption_threshold, + &time_slice, &next_thread,&suspended_thread); + + /* Is this the lowest priority thread in the system trying to use TX services ? */ + if (priority > _ux_system -> ux_system_thread_lowest_priority) + { + + /* We need to remember this thread priority. */ + _ux_system -> ux_system_thread_lowest_priority = priority; + + } + + /* Get ThreadX semaphore instance. */ + status = tx_semaphore_get(semaphore, semaphore_signal); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_semaphore_put.c b/common/core/src/ux_utility_semaphore_put.c new file mode 100644 index 0000000..ba1df05 --- /dev/null +++ b/common/core/src/ux_utility_semaphore_put.c @@ -0,0 +1,79 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_semaphore_put PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets a semaphore signal. */ +/* */ +/* INPUT */ +/* */ +/* semaphore Semaphore to signal */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_semaphore_put ThreadX semaphore put */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_semaphore_put(TX_SEMAPHORE *semaphore) +{ + +UINT status; + + /* Put a ThreadX semaphore. */ + status = tx_semaphore_put(semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_set_interrupt_handler.c b/common/core/src/ux_utility_set_interrupt_handler.c new file mode 100644 index 0000000..fd30c78 --- /dev/null +++ b/common/core/src/ux_utility_set_interrupt_handler.c @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_set_interrupt_handler PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function installs an interrupt handler for USBX. */ +/* */ +/* INPUT */ +/* */ +/* irq Interrupt to install */ +/* interrupt_handler Pointer to interrupt handler */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_set_interrupt_handler(UINT irq, VOID (*interrupt_handler)(VOID)) +{ + + UX_PARAMETER_NOT_USED(interrupt_handler); + UX_PARAMETER_NOT_USED(irq); + + /* Unimplemented, just return. */ + return; +} diff --git a/common/core/src/ux_utility_short_get.c b/common/core/src/ux_utility_short_get.c new file mode 100644 index 0000000..99b43fd --- /dev/null +++ b/common/core/src/ux_utility_short_get.c @@ -0,0 +1,82 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_short_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads a 16-bit value. */ +/* */ +/* INPUT */ +/* */ +/* address Source address */ +/* */ +/* OUTPUT */ +/* */ +/* 16-bit value */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_utility_short_get(UCHAR * address) +{ + +USHORT value; + + + /* In order to make this function endian agnostic and memory alignment + independent, we read a byte at a time from the address. */ + value = (USHORT) *address++; + value |= (USHORT)(*address << 8); + + /* Return to caller. */ + return((ULONG) value); +} + diff --git a/common/core/src/ux_utility_short_get_big_endian.c b/common/core/src/ux_utility_short_get_big_endian.c new file mode 100644 index 0000000..ac3cd35 --- /dev/null +++ b/common/core/src/ux_utility_short_get_big_endian.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_short_get_big_endian PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads a 16-bit value in big endian format. */ +/* */ +/* INPUT */ +/* */ +/* address Source address */ +/* */ +/* OUTPUT */ +/* */ +/* 16-bit value */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_utility_short_get_big_endian(UCHAR * address) +{ + +USHORT value; + + /* We read a byte at a time from the address. */ + value = (USHORT)((*address++) << 8); + value = (USHORT)(value | *address); + + /* Return 16-bit value. */ + return((ULONG) value); +} + diff --git a/common/core/src/ux_utility_short_put.c b/common/core/src/ux_utility_short_put.c new file mode 100644 index 0000000..3655e5b --- /dev/null +++ b/common/core/src/ux_utility_short_put.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_short_put PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a 16-bit value. */ +/* */ +/* INPUT */ +/* */ +/* address Destination address */ +/* value 16-bit value */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_short_put(UCHAR * address, USHORT value) +{ + + /* In order to make this function endian agnostic and memory alignment + independent, we write a byte at a time from the address */ + *address++ = (UCHAR) (value & 0xff); + *address = (UCHAR) ((value >> 8) & 0xff); + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_utility_short_put_big_endian.c b/common/core/src/ux_utility_short_put_big_endian.c new file mode 100644 index 0000000..f382255 --- /dev/null +++ b/common/core/src/ux_utility_short_put_big_endian.c @@ -0,0 +1,89 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_short_put_big_endian PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a 16-bit value in big endian format. */ +/* */ +/* INPUT */ +/* */ +/* address Destination address */ +/* value 16-bit value */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_short_put_big_endian(UCHAR * address, USHORT value) +{ + +USHORT low_byte_value; +USHORT high_byte_value; + + + /* First we swap the value bytes. */ + low_byte_value = value >> 8; + high_byte_value = (USHORT)(value<< 8); + value = high_byte_value | low_byte_value; + + /* In order to make this function endian agnostic and memory alignment + independent, we write a byte at a time from the address. */ + *address++ = (UCHAR) (value & 0xff); + *address= (UCHAR) ((value >> 8) & 0xff); + + /* Return to caller. */ + return; +} + diff --git a/common/core/src/ux_utility_string_length_check.c b/common/core/src/ux_utility_string_length_check.c new file mode 100644 index 0000000..4ecc3cb --- /dev/null +++ b/common/core/src/ux_utility_string_length_check.c @@ -0,0 +1,110 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_string_length_check PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks if a NULL-terminated C string reaches its end */ +/* before specified length exceeds. */ +/* */ +/* On success the actual length of C string is written back to UINT */ +/* variable pointed by string_length_ptr (if not NULL). */ +/* Otherwise the variable keeps untouched. */ +/* */ +/* INPUT */ +/* */ +/* string Pointer to string */ +/* string_length_ptr Pointer to UINT to receive */ +/* the string length */ +/* max_string_length Max string length */ +/* */ +/* OUTPUT */ +/* */ +/* returns success if the string length was less than the max length, */ +/* else it returns error */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_string_length_check(UCHAR *string, UINT *string_length_ptr, UINT max_string_length) +{ + +UINT string_length; + + + if (string == UX_NULL) + return(UX_ERROR); + + string_length = 0; + + while (1) + { + + if (string[string_length] == '\0') + break; + + string_length++; + if (string_length > max_string_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, UX_ERROR); + + return(UX_ERROR); + } + } + + if (string_length_ptr) + *string_length_ptr = string_length; + + return(UX_SUCCESS); +} + diff --git a/common/core/src/ux_utility_string_length_get.c b/common/core/src/ux_utility_string_length_get.c new file mode 100644 index 0000000..6522612 --- /dev/null +++ b/common/core/src/ux_utility_string_length_get.c @@ -0,0 +1,91 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_string_length_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function derives the length of a NULL-terminated string. */ +/* */ +/* This function is deprecated, for the possible issue of operating on */ +/* a buffer that is not NULL-terminated. As a replacement, */ +/* _ux_utility_string_length_check should be used, where the length of */ +/* the buffer is introduced to validate the string by checking for the */ +/* NULL-terminator within the buffer length. */ +/* */ +/* INPUT */ +/* */ +/* string Pointer to string */ +/* */ +/* OUTPUT */ +/* */ +/* length of string */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_utility_string_length_get(UCHAR *string) +{ + +ULONG length = 0; + + /* Loop to find the length of the string. */ + length = 0; + while (string[length]) + { + + /* Move to next position. */ + length++; + } + + /* Return length to caller. */ + return(length); +} + diff --git a/common/core/src/ux_utility_string_to_unicode.c b/common/core/src/ux_utility_string_to_unicode.c new file mode 100644 index 0000000..6ec0b47 --- /dev/null +++ b/common/core/src/ux_utility_string_to_unicode.c @@ -0,0 +1,109 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_string_to_unicode PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function converts a ascii string to a unicode string. */ +/* */ +/* Note: */ +/* The unicode string length (including NULL-terminator) is limited by */ +/* length in a byte, so max ascii string length must be no more than */ +/* 254 (NULL-terminator excluded). Only first 254 characters */ +/* are converted if the string is too long. */ +/* The buffer of destination must have enough space for result, at */ +/* least 1 + (strlen(source) + 1) * 2 bytes. */ +/* */ +/* INPUT */ +/* */ +/* source Ascii String */ +/* destination Unicode String */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_string_length_check Check and return C string */ +/* length */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_string_to_unicode(UCHAR *source, UCHAR *destination) +{ + +UINT string_length; + + /* Get the ascii string length, when there is error length is not modified so max length is used. */ + string_length = 254; + _ux_utility_string_length_check(source, &string_length, 254); + + /* Set the length of the string as the first byte of the unicode string. + The length is casted as a byte since Unicode strings cannot be more than 255 chars. */ + *destination++ = (UCHAR)(string_length + 1); + + while(string_length--) + { + /* First character is from the source. */ + *destination++ = *source++; + + /* Second character of unicode word is 0. */ + *destination++ = 0; + } + + /* Finish with a 0. */ + *destination++ = 0; + + /* Finish with a 0. */ + *destination++ = 0; + + /* We are done. */ + return; +} + diff --git a/common/core/src/ux_utility_thread_create.c b/common/core/src/ux_utility_thread_create.c new file mode 100644 index 0000000..0a5d969 --- /dev/null +++ b/common/core/src/ux_utility_thread_create.c @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_thread_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a thread for USBX. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* name Pointer to thread name string */ +/* entry_function Entry function of the thread */ +/* entry_input 32-bit input value to thread */ +/* stack_start Pointer to start of stack */ +/* stack_size Stack size in bytes */ +/* priority Priority of thread (0-31) */ +/* preempt_threshold Preemption threshold */ +/* time_slice Thread time-slice value */ +/* auto_start Automatic start selection */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_create ThreadX create thread function*/ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_thread_create(TX_THREAD *thread_ptr, CHAR *name, + VOID (*entry_function)(ULONG), ULONG entry_input, + VOID *stack_start, ULONG stack_size, + UINT priority, UINT preempt_threshold, + ULONG time_slice, UINT auto_start) +{ + +UINT status; + + + /* Call ThreadX to create USBX thread. */ + status = tx_thread_create(thread_ptr,name,entry_function,entry_input, + stack_start,stack_size, priority,preempt_threshold,time_slice,auto_start); + + /* Check for status. */ + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, status); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_THREAD_ERROR, thread_ptr, 0, 0, UX_TRACE_ERRORS, 0, 0) + + } + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_thread_delete.c b/common/core/src/ux_utility_thread_delete.c new file mode 100644 index 0000000..dd9aad5 --- /dev/null +++ b/common/core/src/ux_utility_thread_delete.c @@ -0,0 +1,84 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_thread_delete PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes a thread for USBX. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_terminate ThreadX terminate thread */ +/* tx_thread_delete ThreadX delete thread service */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_thread_delete(TX_THREAD *thread_ptr) +{ + +UINT status; + + + /* Call ThreadX to terminate the USBX thread. */ + tx_thread_terminate(thread_ptr); + + /* Call ThreadX to delete the USBX thread. */ + status = tx_thread_delete(thread_ptr); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_thread_identify.c b/common/core/src/ux_utility_thread_identify.c new file mode 100644 index 0000000..02f640d --- /dev/null +++ b/common/core/src/ux_utility_thread_identify.c @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "tx_thread.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_thread_identify PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function return a pointer to the calling thread. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_identify ThreadX identify function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +TX_THREAD *_ux_utility_thread_identify(VOID) +{ + + + /* If we're under interrupt, the thread returned by tx_thread_identify + is the thread running prior to the ISR. Instead, we set it to null. */ + return(TX_THREAD_GET_SYSTEM_STATE() ? UX_NULL : tx_thread_identify()); +} + diff --git a/common/core/src/ux_utility_thread_relinquish.c b/common/core/src/ux_utility_thread_relinquish.c new file mode 100644 index 0000000..d7f687a --- /dev/null +++ b/common/core/src/ux_utility_thread_relinquish.c @@ -0,0 +1,73 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_thread_relinquish PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function helps the thread relinquish its control. */ +/* */ +/* INPUT */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_relinquish ThreadX relinquish thread */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_thread_relinquish(VOID) +{ + + /* Call ThreadX to relinquish a USBX thread. */ + tx_thread_relinquish(); + +} + diff --git a/common/core/src/ux_utility_thread_resume.c b/common/core/src/ux_utility_thread_resume.c new file mode 100644 index 0000000..2bb13a6 --- /dev/null +++ b/common/core/src/ux_utility_thread_resume.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_thread_resume PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function resumes a thread for USBX. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_resume ThreadX resume thread function*/ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_thread_resume(TX_THREAD *thread_ptr) +{ + +UINT status; + + + /* Call ThreadX to resume USBX thread. */ + status = tx_thread_resume(thread_ptr); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_thread_schedule_other.c b/common/core/src/ux_utility_thread_schedule_other.c new file mode 100644 index 0000000..388031e --- /dev/null +++ b/common/core/src/ux_utility_thread_schedule_other.c @@ -0,0 +1,100 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_thread_priority_change PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function force the scheduling of all other threads. */ +/* */ +/* INPUT */ +/* */ +/* caller_priority Priority to restore. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_identify ThreadX identify */ +/* tx_thread_priority_change ThreadX priority change */ +/* tx_thread_relinquish ThreadX relinquish */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_thread_schedule_other(UINT caller_priority) +{ + +UINT status; +UINT old_priority; +TX_THREAD *my_thread; + + UX_PARAMETER_NOT_USED(caller_priority); + + /* Call TX to know my own tread. */ + my_thread = tx_thread_identify(); + + /* Call ThreadX to change thread priority . */ + status = tx_thread_priority_change(my_thread, _ux_system -> ux_system_thread_lowest_priority, &old_priority); + + /* Check for error. */ + if (status == TX_SUCCESS) + { + + /* Wait until all other threads passed into the scheduler. */ + _ux_utility_thread_relinquish(); + + /* And now return the priority of the thread to normal. */ + status = tx_thread_priority_change(my_thread, old_priority, &old_priority); + + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_thread_sleep.c b/common/core/src/ux_utility_thread_sleep.c new file mode 100644 index 0000000..cfa494e --- /dev/null +++ b/common/core/src/ux_utility_thread_sleep.c @@ -0,0 +1,79 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_thread_sleep PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function causes the calling thread to sleep for the */ +/* specified number of ticks. */ +/* */ +/* INPUT */ +/* */ +/* ticks Number of ticks to sleep */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_sleep ThreadX sleep function */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_thread_sleep(ULONG ticks) +{ + +UINT status; + + /* Call ThreadX sleep function. */ + status = tx_thread_sleep(ticks); + + return(status); +} + diff --git a/common/core/src/ux_utility_thread_suspend.c b/common/core/src/ux_utility_thread_suspend.c new file mode 100644 index 0000000..304ce18 --- /dev/null +++ b/common/core/src/ux_utility_thread_suspend.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_thread_suspend PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function suspends thread for USBX. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_suspend ThreadX suspend thread service*/ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_thread_suspend(TX_THREAD *thread_ptr) +{ + +UINT status; + + + /* Call ThreadX to suspend USBX thread. */ + status = tx_thread_suspend(thread_ptr); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_timer_create.c b/common/core/src/ux_utility_timer_create.c new file mode 100644 index 0000000..04c3c69 --- /dev/null +++ b/common/core/src/ux_utility_timer_create.c @@ -0,0 +1,90 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_timer_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a timer. */ +/* */ +/* INPUT */ +/* */ +/* timer Pointer to timer */ +/* timer_name Name of timer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* tx_timer_create ThreadX timer create */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_utility_timer_create(TX_TIMER *timer, CHAR *timer_name, VOID (*expiration_function) (ULONG), + ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, + UINT activation_flag) +{ + +UINT status; + + + /* Call ThreadX to create the timer object. */ + status = tx_timer_create(timer, (CHAR *) timer_name, expiration_function, expiration_input, + initial_ticks, reschedule_ticks, activation_flag); + + /* Check status. */ + if (status != UX_SUCCESS) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_UTILITY, status); + + /* Return completion status. */ + return(status); +} + diff --git a/common/core/src/ux_utility_unicode_to_string.c b/common/core/src/ux_utility_unicode_to_string.c new file mode 100644 index 0000000..aeb1564 --- /dev/null +++ b/common/core/src/ux_utility_unicode_to_string.c @@ -0,0 +1,94 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_unicode_to_string PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function converts a unicode string to a zero terminated */ +/* ascii string. */ +/* */ +/* INPUT */ +/* */ +/* source Unicode String */ +/* destination Ascii String */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_utility_unicode_to_string(UCHAR *source, UCHAR *destination) +{ +ULONG string_length; + + /* Obtain the length of the unicode string. This is the first byte*/ + string_length = (ULONG) *source++; + + /* Parse the unicode string. First byte is always 0, second byte is the + ASCII character. */ + while(string_length--) + { + /* First character is from the source. */ + *destination++ = *source++; + + /* Second character of unicode word is 0. */ + source++; + } + + /* We are done with the ascii string. Insert a zero at the end. */ + *destination = 0; + + /* Finished. */ + return; +} + diff --git a/common/core/src/ux_utility_virtual_address.c b/common/core/src/ux_utility_virtual_address.c new file mode 100644 index 0000000..5bb4e95 --- /dev/null +++ b/common/core/src/ux_utility_virtual_address.c @@ -0,0 +1,81 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Utility */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_utility_virtual_address PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns a virtual address given the supplied */ +/* physical address. */ +/* */ +/* INPUT */ +/* */ +/* physical_address Virtual address */ +/* */ +/* OUTPUT */ +/* */ +/* virtual_address Physical address */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Components */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID *_ux_utility_virtual_address(VOID *physical_address) +{ + +VOID *virtual_address; + + /* Any code to translate the physical address into a virtual address + will be below. If there is no translation, the physical address= + the virtual address. */ + + virtual_address = physical_address; + return(virtual_address); +} + diff --git a/common/usbx_device_classes/CMakeLists.txt b/common/usbx_device_classes/CMakeLists.txt new file mode 100644 index 0000000..10f9996 --- /dev/null +++ b/common/usbx_device_classes/CMakeLists.txt @@ -0,0 +1,151 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio10_control_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio20_control_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_frame_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_frame_free.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_frame_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_read_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_reception_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read16.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read24.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read32.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_sample_read8.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_stream_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_transmission_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_unitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_frame_commit.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_frame_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_audio_write_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_bulkin_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_bulkout_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_unitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_acm_write_with_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_bulkin_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_bulkout_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_change.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_uninitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_cdc_ecm_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_dfu_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_descriptor_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_event_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_event_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_report_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_report_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_hid_uninitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_data.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_device_info_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_device_prop_desc_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_device_prop_value_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_device_prop_value_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_device_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_event_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_event_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_data_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_data_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_handles_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_info_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_prop_desc_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_prop_value_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_prop_value_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_props_supported_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_references_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_object_references_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_objects_number_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_partial_object_data_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_response_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_storage_format.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_storage_id_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_storage_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_pima_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_bulkin_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_bulkout_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_interrupt_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_msg_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_msg_keep_alive.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_msg_query.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_msg_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_msg_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_rndis_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_control_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_csw_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_format.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_get_configuration.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_get_performance.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_get_status_notification.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_inquiry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_mode_select.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_mode_sense.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_prevent_allow_media_removal.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read_capacity.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read_disk_information.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read_dvd_structure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read_format_capacity.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_read_toc.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_report_key.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_request_sense.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_start_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_synchronize_cache.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_test_ready.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_uninitialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_verify.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_device_class_storage_write.c + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/common/usbx_device_classes/inc/ux_device_class_audio.h b/common/usbx_device_classes/inc/ux_device_class_audio.h new file mode 100644 index 0000000..2ed7cfb --- /dev/null +++ b/common/usbx_device_classes/inc/ux_device_class_audio.h @@ -0,0 +1,421 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_audio.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX audio class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_AUDIO_H +#define UX_DEVICE_CLASS_AUDIO_H + +/* Define Audio Class function (AF) constants. */ + +#define UX_DEVICE_CLASS_AUDIO_FUNCTION_CLASS 1 +#define UX_DEVICE_CLASS_AUDIO_FUNCTION_SUBCLASS_UNDEFINED 0 +#define UX_DEVICE_CLASS_AUDIO_FUNCTION_PROTOCOL_UNDEFINED 0 +#define UX_DEVICE_CLASS_AUDIO_FUNCTION_PROTOCOL_VERSION_02_00 0x20 + +/* Define Audio Class interface constants. */ + +#define UX_DEVICE_CLASS_AUDIO_CLASS 1 + +#define UX_DEVICE_CLASS_AUDIO_SUBCLASS_UNDEFINED 0 +#define UX_DEVICE_CLASS_AUDIO_SUBCLASS_CONTROL 1 +#define UX_DEVICE_CLASS_AUDIO_SUBCLASS_AUDIOSTREAMING 2 +#define UX_DEVICE_CLASS_AUDIO_SUBCLASS_MIDISTREAMING 3 + +#define UX_DEVICE_CLASS_AUDIO_PROTOCOL_UNDEFINED 0 +#define UX_DEVICE_CLASS_AUTIO_PROTOCOL_VERSION_02_00 0x20 + + +/* Define Audio Class-specific (CS) descriptor types. */ + +#define UX_DEVICE_CLASS_AUDIO_CS_UNDEFINED 0x20 +#define UX_DEVICE_CLASS_AUDIO_CS_DEVICE 0x21 +#define UX_DEVICE_CLASS_AUDIO_CS_CONFIGURATION 0x22 +#define UX_DEVICE_CLASS_AUDIO_CS_STRING 0x23 +#define UX_DEVICE_CLASS_AUDIO_CS_INTERFACE 0x24 +#define UX_DEVICE_CLASS_AUDIO_CS_ENDPOINT 0x25 + + +/* Define Audio Class specific AC interface descriptor subclasses. */ + +#define UX_DEVICE_CLASS_AUDIO_AC_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO_AC_HEADER 0x01 +#define UX_DEVICE_CLASS_AUDIO_AC_INPUT_TERMINAL 0x02 +#define UX_DEVICE_CLASS_AUDIO_AC_OUTPUT_TERMINAL 0x03 +#define UX_DEVICE_CLASS_AUDIO_AC_FEATURE_UNIT 0x06 + + +/* Define Audio Class specific AS interface descriptor subclasses. */ + +#define UX_DEVICE_CLASS_AUDIO_AS_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO_AS_GENERAL 0x01 +#define UX_DEVICE_CLASS_AUDIO_AS_FORMAT_TYPE 0x02 + + +/* Define Audio Class data endpoint descriptor attributes. */ + +#define UX_DEVICE_CLASS_AUDIO_EP_TRANSFER_TYPE_MASK (0x3u<<0) +#define UX_DEVICE_CLASS_AUDIO_EP_TRANSFER_TYPE_ISOCHRONOUS (0x1u<<0) + +#define UX_DEVICE_CLASS_AUDIO_EP_SYNCHRONIZATION_TYPE_MASK (0x3u<<2) +#define UX_DEVICE_CLASS_AUDIO_EP_SYNCHRONIZATION_TYPE_ASYNCHRONOUS (0x1u<<2) +#define UX_DEVICE_CLASS_AUDIO_EP_SYNCHRONIZATION_TYPE_ADAPTIVE (0x2u<<2) +#define UX_DEVICE_CLASS_AUDIO_EP_SYNCHRONIZATION_TYPE_SYNCHRONOUS (0x3u<<2) + +#define UX_DEVICE_CLASS_AUDIO_EP_USAGE_TYPE_MASK (0x3u<<4) +#define UX_DEVICE_CLASS_AUDIO_EP_USAGE_TYPE_DATA (0x0u<<4) +#define UX_DEVICE_CLASS_AUDIO_EP_USAGE_TYPE_IMPLICIT_FEEDBACK (0x2u<<4) + + +/* Define Audio Class specific endpoint descriptor subtypes. */ + +#define UX_DEVICE_CLASS_AUDIO_EP_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO_EP_GENERAL 0x01 + + +/* Define Audio Class specific request codes. */ + +#define UX_DEVICE_CLASS_AUDIO_REQUEST_CODE_UNDEFINED 0x00 + +#define UX_DEVICE_CLASS_AUDIO_bmRequestType_GET_INTERFACE 0xA1 +#define UX_DEVICE_CLASS_AUDIO_bmRequestType_SET_INTERFACE 0x21 +#define UX_DEVICE_CLASS_AUDIO_bmRequestType_GET_ENDPOINT 0xA2 +#define UX_DEVICE_CLASS_AUDIO_bmRequestType_SET_ENDPOINT 0x22 + +#define UX_DEVICE_CLASS_AUDIO_REQUEST_REQUEST_TYPE 0 +#define UX_DEVICE_CLASS_AUDIO_REQUEST_REQUEST 1 + +#define UX_DEVICE_CLASS_AUDIO_REQUEST_VALUE_LOW 2 +#define UX_DEVICE_CLASS_AUDIO_REQUEST_CHANNEL_NUMBER 2 +#define UX_DEVICE_CLASS_AUDIO_REQUEST_CN 2 +#define UX_DEVICE_CLASS_AUDIO_REQUEST_MIXER_CONTROL_NUMBER 2 +#define UX_DEVICE_CLASS_AUDIO_REQUEST_MCN 2 + +#define UX_DEVICE_CLASS_AUDIO_REQUEST_VALUE_HIGH 3 +#define UX_DEVICE_CLASS_AUDIO_REQUEST_CONTROL_SELECTOR 3 +#define UX_DEVICE_CLASS_AUDIO_REQUEST_CS 3 + +#define UX_DEVICE_CLASS_AUDIO_REQUEST_INDEX_LOW 4 +#define UX_DEVICE_CLASS_AUDIO_REQUEST_ENDPOINT 4 +#define UX_DEVICE_CLASS_AUDIO_REQUEST_INTERFACE 4 + +#define UX_DEVICE_CLASS_AUDIO_REQUEST_INDEX_HIGH 5 +#define UX_DEVICE_CLASS_AUDIO_REQUEST_ENEITY_ID 5 + +#define UX_DEVICE_CLASS_AUDIO_REQUEST_LENGTH 6 + + +/* Define Audio Class terminal types. */ + +#define UX_DEVICE_CLASS_AUDIO_UNDEFINED 0x0100 +#define UX_DEVICE_CLASS_AUDIO_USB_STREAMING 0x0101 +#define UX_DEVICE_CLASS_AUDIO_USB_VENDOR_SPECIFIC 0x01FF + + +/* Define Audio Class input terminal types. */ + +#define UX_DEVICE_CLASS_AUDIO_INPUT 0x0200 +#define UX_DEVICE_CLASS_AUDIO_MICROPHONE 0x0201 +#define UX_DEVICE_CLASS_AUDIO_DESKTOP_MICROPHONE 0x0202 +#define UX_DEVICE_CLASS_AUDIO_PERSONAL_MICROPHONE 0x0203 +#define UX_DEVICE_CLASS_AUDIO_OMNI_DIRECTIONAL_MICROPHONE 0x0204 +#define UX_DEVICE_CLASS_AUDIO_MICROPHONE_ARRAY 0x0205 +#define UX_DEVICE_CLASS_AUDIO_PROCESSING_MICROPHONE_ARRAY 0x0206 + + +/* Define Audio Class output terminal types. */ + +#define UX_DEVICE_CLASS_AUDIO_OUTPUT 0x0300 +#define UX_DEVICE_CLASS_AUDIO_SPEAKER 0x0301 +#define UX_DEVICE_CLASS_AUDIO_HEADPHONES 0x0302 +#define UX_DEVICE_CLASS_AUDIO_HEAD_MOUNTED_DISPLAY 0x0303 +#define UX_DEVICE_CLASS_AUDIO_DESKTOP_SPEAKER 0x0304 +#define UX_DEVICE_CLASS_AUDIO_ROOM_SPEAKER 0x0305 +#define UX_DEVICE_CLASS_AUDIO_COMMUNICATION_SPEAKER 0x0306 +#define UX_DEVICE_CLASS_AUDIO_LOW_FREQUENCY_SPEAKER 0x0307 + + +/* Define Audio Class bidirectional terminal types. */ + +#define UX_DEVICE_CLASS_AUDIO_BIDIRECTIONAL_UNDEFINED 0x0400 +#define UX_DEVICE_CLASS_AUDIO_HANDSET 0x0401 +#define UX_DEVICE_CLASS_AUDIO_HEADSET 0x0402 +#define UX_DEVICE_CLASS_AUDIO_SPEAKERPHONE 0x0403 +#define UX_DEVICE_CLASS_AUDIO_ECHO_SUPRESS_SPEAKERPHONE 0x0404 +#define UX_DEVICE_CLASS_AUDIO_ECHO_CANCEL_SPEAKERPHONE 0x0405 + + +/* Define Audio Class telephony terminal types. */ + +#define UX_DEVICE_CLASS_AUDIO_TELEPHONTY_UNDEFINED 0x0500 +#define UX_DEVICE_CLASS_AUDIO_PHONE_LINE 0x0501 +#define UX_DEVICE_CLASS_AUDIO_TELEPHONE 0x0502 +#define UX_DEVICE_CLASS_AUDIO_DOWN_LINE_PHONE 0x0503 + + +/* Define Audio Class external terminal types. */ + +#define UX_DEVICE_CLASS_AUDIO_EXTERNAL_UNDEFINED 0x0600 +#define UX_DEVICE_CLASS_AUDIO_ANALOG_CONNECTOR 0x0601 +#define UX_DEVICE_CLASS_AUDIO_DIGITAL_AUDIO_INTERFACE 0x0602 +#define UX_DEVICE_CLASS_AUDIO_LINE_CONNECTOR 0x0603 +#define UX_DEVICE_CLASS_AUDIO_LEGACY_AUDIO_CONNECTOR 0x0604 +#define UX_DEVICE_CLASS_AUDIO_S_PDIF_INTERFACE 0x0605 +#define UX_DEVICE_CLASS_AUDIO_1394_DA_STREAM 0x0606 +#define UX_DEVICE_CLASS_AUDIO_1394_DV_STREAM_SOUNDTRACK 0x0607 +#define UX_DEVICE_CLASS_AUDIO_ADAT_LIGHTPIPE 0x0608 +#define UX_DEVICE_CLASS_AUDIO_TDIF 0x0609 +#define UX_DEVICE_CLASS_AUDIO_MADI 0x060A + + +/* Define Audio Class embedded function terminal types. */ + +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_UNDEFINED 0x0700 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_LEVEL_CALIB_NOISE_SRC 0x0701 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_EQUALIZATION_NOISE 0x0702 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_CD_PLAYER 0x0703 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_DAT 0x0704 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_DCC 0x0705 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_MINIDISK 0x0706 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_ANALOG_TAPE 0x0707 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_PHONOGRAPH 0x0708 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_VCR_AUDIO 0x0709 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_VIDEO_DISC_AUDIO 0x070A +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_DVD_AUDIO 0x070B +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_TV_TUNER_AUDIO 0x070C +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_SATELLITE_RECEIVER_AUDIO 0x070D +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_CABLE_TUNER_AUDIO 0x070E +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_DSS_AUDIO 0x070F +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_RADIO_RECEIVER 0x0710 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_RADIO_TRANSMITTER 0x0711 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_MULTI_TRACK_RECORDER 0x0712 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_SYNTHESIZER 0x0713 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_PIANO 0x0714 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_GUITAR 0x0715 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_DRUMS_RHYTHM 0x0716 +#define UX_DEVICE_CLASS_AUDIO_EMBEDDED_OTHER 0x0717 + + +/* Define Audio Class encoding format types. */ + +#define UX_DEVICE_CLASS_AUDIO_FORMAT_TYPE_UNDEFINED 0 +#define UX_DEVICE_CLASS_AUDIO_FORMAT_TYPE_I 1 +#define UX_DEVICE_CLASS_AUDIO_FORMAT_TYPE_II 2 +#define UX_DEVICE_CLASS_AUDIO_FORMAT_TYPE_III 3 +#define UX_DEVICE_CLASS_AUDIO_FORMAT_TYPE_IV 4 +#define UX_DEVICE_CLASS_AUDIO_EXT_FORMAT_TYPE_I 0x81 +#define UX_DEVICE_CLASS_AUDIO_EXT_FORMAT_TYPE_II 0x82 +#define UX_DEVICE_CLASS_AUDIO_EXT_FORMAT_TYPE_III 0x83 + + +/* Define channels. */ + +#define UX_DEVICE_CLASS_AUDIO_MASTER_CHANNEL 0 +#define UX_DEVICE_CLASS_AUDIO_CHANNEL_1 1 +#define UX_DEVICE_CLASS_AUDIO_CHANNEL_2 2 +#define UX_DEVICE_CLASS_AUDIO_CHANNEL_3 3 +#define UX_DEVICE_CLASS_AUDIO_CHANNEL_4 4 +#define UX_DEVICE_CLASS_AUDIO_CHANNEL_5 5 +#define UX_DEVICE_CLASS_AUDIO_CHANNEL_6 6 +#define UX_DEVICE_CLASS_AUDIO_CHANNEL_7 7 +#define UX_DEVICE_CLASS_AUDIO_CHANNEL_8 8 +#define UX_DEVICE_CLASS_AUDIO_CHANNEL_9 9 + + +/* Define IOCTL code. + ux_device_class_audio_ioctl(audio, IOCTL_CODE, parameter). + */ + +#define UX_DEVICE_CLASS_AUDIO_IOCTL_GET_ARG 1 + + +/* Define Audio Class callback structure. */ + +struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT; +struct UX_DEVICE_CLASS_AUDIO_STRUCT; + +typedef struct UX_DEVICE_CLASS_AUDIO_CALLBACKS_STRUCT +{ + + VOID (*ux_slave_class_audio_instance_activate)(VOID *); + VOID (*ux_slave_class_audio_instance_deactivate)(VOID *); + UINT (*ux_device_class_audio_control_process)(struct UX_DEVICE_CLASS_AUDIO_STRUCT *, UX_SLAVE_TRANSFER *); + VOID *ux_device_class_audio_arg; +} UX_DEVICE_CLASS_AUDIO_CALLBACKS; + +typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS_STRUCT +{ + VOID (*ux_device_class_audio_stream_change)(struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT *, ULONG); + VOID (*ux_device_class_audio_stream_frame_done)(struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT *, ULONG); +} UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS; + + +/* Define Audio Class Calling Parameter structure */ + +typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_PARAMETER_STRUCT +{ + ULONG ux_device_class_audio_stream_parameter_thread_stack_size; + VOID (*ux_device_class_audio_stream_parameter_thread_entry)(ULONG id); + UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS ux_device_class_audio_stream_parameter_callbacks; + + ULONG ux_device_class_audio_stream_parameter_max_frame_buffer_size; + ULONG ux_device_class_audio_stream_parameter_max_frame_buffer_nb; +} UX_DEVICE_CLASS_AUDIO_STREAM_PARAMETER; + +typedef struct UX_DEVICE_CLASS_AUDIO_PARAMETER_STRUCT +{ + ULONG ux_device_class_audio_parameter_master_interface; + UX_DEVICE_CLASS_AUDIO_CALLBACKS ux_device_class_audio_parameter_callbacks; + + ULONG ux_device_class_audio_parameter_streams_nb; + UX_DEVICE_CLASS_AUDIO_STREAM_PARAMETER *ux_device_class_audio_parameter_streams; +} UX_DEVICE_CLASS_AUDIO_PARAMETER; + + +/* Define Audio Class instance structure. */ + +typedef struct UX_DEVICE_CLASS_AUDIO_FRAME_STRUCT +{ + + ULONG ux_device_class_audio_frame_length; + ULONG ux_device_class_audio_frame_pos; + UCHAR ux_device_class_audio_frame_data[4]; +} UX_DEVICE_CLASS_AUDIO_FRAME; + +typedef struct UX_DEVICE_CLASS_AUDIO_STREAM_STRUCT +{ + + struct UX_DEVICE_CLASS_AUDIO_STRUCT *ux_device_class_audio_stream_audio; + UX_SLAVE_INTERFACE *ux_device_class_audio_stream_interface; + UX_SLAVE_ENDPOINT *ux_device_class_audio_stream_endpoint; + + UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS ux_device_class_audio_stream_callbacks; + + UCHAR *ux_device_class_audio_stream_thread_stack; + TX_THREAD ux_device_class_audio_stream_thread; + + UCHAR *ux_device_class_audio_stream_buffer; + ULONG ux_device_class_audio_stream_buffer_size; + ULONG ux_device_class_audio_stream_frame_buffer_size; + + UX_DEVICE_CLASS_AUDIO_FRAME *ux_device_class_audio_stream_transfer_pos; + UX_DEVICE_CLASS_AUDIO_FRAME *ux_device_class_audio_stream_access_pos; +} UX_DEVICE_CLASS_AUDIO_STREAM; + +typedef struct UX_DEVICE_CLASS_AUDIO_STRUCT +{ + + UX_SLAVE_CLASS *ux_device_class_audio_class; + UX_SLAVE_DEVICE *ux_device_class_audio_device; + UX_SLAVE_INTERFACE *ux_device_class_audio_interface; + + UX_DEVICE_CLASS_AUDIO_CALLBACKS ux_device_class_audio_callbacks; + + ULONG ux_device_class_audio_streams_nb; + UX_DEVICE_CLASS_AUDIO_STREAM *ux_device_class_audio_streams; +} UX_DEVICE_CLASS_AUDIO; + + +/* Define Audio Class function prototypes. */ + +UINT _ux_device_class_audio_initialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_audio_uninitialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_audio_activate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_audio_change(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_audio_deactivate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_audio_control_request(UX_SLAVE_CLASS_COMMAND *command); + +UINT _ux_device_class_audio_entry(UX_SLAVE_CLASS_COMMAND *command); + +UINT _ux_device_class_audio_ioctl(UX_DEVICE_CLASS_AUDIO *audio, ULONG ioctl_function, + VOID *parameter); + +UINT _ux_device_class_audio_stream_get(UX_DEVICE_CLASS_AUDIO *audio, ULONG stream_index, UX_DEVICE_CLASS_AUDIO_STREAM **stream); + +VOID _ux_device_class_audio_write_thread_entry(ULONG audio_stream); +VOID _ux_device_class_audio_read_thread_entry(ULONG audio_stream); + +UINT _ux_device_class_audio_reception_start(UX_DEVICE_CLASS_AUDIO_STREAM *audio); +UINT _ux_device_class_audio_sample_read8(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UCHAR *sample); +UINT _ux_device_class_audio_sample_read16(UX_DEVICE_CLASS_AUDIO_STREAM *audio, USHORT *sample); +UINT _ux_device_class_audio_sample_read24(UX_DEVICE_CLASS_AUDIO_STREAM *audio, ULONG *sample); +UINT _ux_device_class_audio_sample_read32(UX_DEVICE_CLASS_AUDIO_STREAM *audio, ULONG *sample); + +UINT _ux_device_class_audio_read_frame_get(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UCHAR **frame_data, ULONG *frame_length); +UINT _ux_device_class_audio_read_frame_free(UX_DEVICE_CLASS_AUDIO_STREAM *audio); + +UINT _ux_device_class_audio_transmission_start(UX_DEVICE_CLASS_AUDIO_STREAM *audio); +UINT _ux_device_class_audio_frame_write(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UCHAR *frame, ULONG length); + +UINT _ux_device_class_audio_write_frame_get(UX_DEVICE_CLASS_AUDIO_STREAM *audio, UCHAR **buffer, ULONG *max_length); +UINT _ux_device_class_audio_write_frame_commit(UX_DEVICE_CLASS_AUDIO_STREAM *audio, ULONG length); + + +/* Define Device Class Audio API prototypes. */ + +#define ux_device_class_audio_entry _ux_device_class_audio_entry + +#define ux_device_class_audio_read_thread_entry _ux_device_class_audio_read_thread_entry +#define ux_device_class_audio_write_thread_entry _ux_device_class_audio_write_thread_entry + +#define ux_device_class_audio_stream_get _ux_device_class_audio_stream_get + +#define ux_device_class_audio_reception_start _ux_device_class_audio_reception_start +#define ux_device_class_audio_sample_read8 _ux_device_class_audio_sample_read8 +#define ux_device_class_audio_sample_read16 _ux_device_class_audio_sample_read16 +#define ux_device_class_audio_sample_read24 _ux_device_class_audio_sample_read24 +#define ux_device_class_audio_sample_read32 _ux_device_class_audio_sample_read32 + +#define ux_device_class_audio_read_frame_get _ux_device_class_audio_read_frame_get +#define ux_device_class_audio_read_frame_free _ux_device_class_audio_read_frame_free + +#define ux_device_class_audio_transmission_start _ux_device_class_audio_transmission_start +#define ux_device_class_audio_frame_write _ux_device_class_audio_frame_write + +#define ux_device_class_audio_write_frame_get _ux_device_class_audio_write_frame_get +#define ux_device_class_audio_write_frame_commit _ux_device_class_audio_write_frame_commit + +#define ux_device_class_audio_ioctl _ux_device_class_audio_ioctl + +#endif /* ifndef UX_DEVICE_CLASS_AUDIO_H */ diff --git a/common/usbx_device_classes/inc/ux_device_class_audio10.h b/common/usbx_device_classes/inc/ux_device_class_audio10.h new file mode 100644 index 0000000..4d3572e --- /dev/null +++ b/common/usbx_device_classes/inc/ux_device_class_audio10.h @@ -0,0 +1,360 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_audio10.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX audio class version 1.0. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_AUDIO10_H +#define UX_DEVICE_CLASS_AUDIO10_H + + +/* Define Audio Class specific AC interface descriptor subclasses. */ + +#define UX_DEVICE_CLASS_AUDIO10_AC_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO10_AC_HEADER 0x01 +#define UX_DEVICE_CLASS_AUDIO10_AC_INPUT_TERMINAL 0x02 +#define UX_DEVICE_CLASS_AUDIO10_AC_OUTPUT_TERMINAL 0x03 +#define UX_DEVICE_CLASS_AUDIO10_AC_MIXER_UNIT 0x04 +#define UX_DEVICE_CLASS_AUDIO10_AC_SELECTOR_UNIT 0x05 +#define UX_DEVICE_CLASS_AUDIO10_AC_FEATURE_UNIT 0x06 +#define UX_DEVICE_CLASS_AUDIO10_AC_PROCESSING_UNIT 0x07 +#define UX_DEVICE_CLASS_AUDIO10_AC_EXTENSION_UNIT 0x08 + + +/* Define Audio Class specific AS interface descriptor subclasses. */ + +#define UX_DEVICE_CLASS_AUDIO10_AS_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO10_AS_GENERAL 0x01 +#define UX_DEVICE_CLASS_AUDIO10_AS_FORMAT_TYPE 0x02 +#define UX_DEVICE_CLASS_AUDIO10_AS_FORMAT_SPECIFIC 0x03 + + +/* Define Audio Class specific endpoint descriptor subtypes. */ + +#define UX_DEVICE_CLASS_AUDIO10_EP_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO10_EP_GENERAL 0x01 + + +/* Define Audio Class specific request codes. */ + +#define UX_DEVICE_CLASS_AUDIO10_REQUEST_CODE_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO10_SET_CUR 0x01 +#define UX_DEVICE_CLASS_AUDIO10_GET_CUR 0x81 +#define UX_DEVICE_CLASS_AUDIO10_SET_MIN 0x02 +#define UX_DEVICE_CLASS_AUDIO10_GET_MIN 0x82 +#define UX_DEVICE_CLASS_AUDIO10_SET_MAX 0x03 +#define UX_DEVICE_CLASS_AUDIO10_GET_MAX 0x83 +#define UX_DEVICE_CLASS_AUDIO10_SET_RES 0x04 +#define UX_DEVICE_CLASS_AUDIO10_GET_RES 0x84 +#define UX_DEVICE_CLASS_AUDIO10_SET_MEM 0x05 +#define UX_DEVICE_CLASS_AUDIO10_GET_MEM 0x85 +#define UX_DEVICE_CLASS_AUDIO10_GET_STAT 0xFF + + +/* Define Audio Class specific terminal control selectors. */ + +#define UX_DEVICE_CLASS_AUDIO10_TE_CONTROL_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO10_TE_COPY_PROTECT_CONTROL 0x01 + + +/* Define Audio Class specific feature unit control selectors. */ + +#define UX_DEVICE_CLASS_AUDIO10_FU_CONTROL_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO10_FU_MUTE_CONTROL 0x01 +#define UX_DEVICE_CLASS_AUDIO10_FU_VOLUME_CONTROL 0x02 +#define UX_DEVICE_CLASS_AUDIO10_FU_BASS_CONTROL 0x03 +#define UX_DEVICE_CLASS_AUDIO10_FU_MID_CONTROL 0x04 +#define UX_DEVICE_CLASS_AUDIO10_FU_TREBLE_CONTROL 0x05 +#define UX_DEVICE_CLASS_AUDIO10_FU_GRAPHIC_EQUALIZER_CONTROL 0x06 +#define UX_DEVICE_CLASS_AUDIO10_FU_AUTOMATIC_GAIN_CONTROL 0x07 +#define UX_DEVICE_CLASS_AUDIO10_FU_DELAY_CONTROL 0x08 +#define UX_DEVICE_CLASS_AUDIO10_FU_BASS_BOOST_CONTROL 0x09 +#define UX_DEVICE_CLASS_AUDIO10_FU_LOUNDNESS_CONTROL 0x0A + + +/* Define Audio Class encoding format types. */ + +#define UX_DEVICE_CLASS_AUDIO10_FORMAT_PCM 1 +#define UX_DEVICE_CLASS_AUDIO10_FORMAT_PCM8 2 +#define UX_DEVICE_CLASS_AUDIO10_FORMAT_IEEE_FLOAT 3 +#define UX_DEVICE_CLASS_AUDIO10_FORMAT_ALAW 4 +#define UX_DEVICE_CLASS_AUDIO10_FORMAT_MULAW 5 + + +/* Audio Class Control interface structures. */ + +typedef struct UX_DEVICE_CLASS_AUDIO10_AC_HEADER1_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bcdADC; + ULONG wTotalLength; + ULONG bInCollection; + ULONG baInterfaceNr1; +} UX_DEVICE_CLASS_AUDIO10_AC_HEADER1_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO10_AC_HEADER2_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bcdADC; + ULONG wTotalLength; + ULONG bInCollection; + ULONG baInterfaceNr1; + ULONG baInterfaceNr2; +} UX_DEVICE_CLASS_AUDIO10_AC_HEADER2_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO10_AC_HEADER3_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bcdADC; + ULONG wTotalLength; + ULONG bInCollection; + ULONG baInterfaceNr1; + ULONG baInterfaceNr2; + ULONG baInterfaceNr3; +} UX_DEVICE_CLASS_AUDIO10_AC_HEADER3_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO10_AC_HEADER6_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bcdADC; + ULONG wTotalLength; + ULONG bInCollection; + ULONG baInterfaceNr1; + ULONG baInterfaceNr2; + ULONG baInterfaceNr3; + ULONG baInterfaceNr4; + ULONG baInterfaceNr5; + ULONG baInterfaceNr6; +} UX_DEVICE_CLASS_AUDIO10_AC_HEADER6_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO10_AC_HEADER7_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bcdADC; + ULONG wTotalLength; + ULONG bInCollection; + ULONG baInterfaceNr1; + ULONG baInterfaceNr2; + ULONG baInterfaceNr3; + ULONG baInterfaceNr4; + ULONG baInterfaceNr5; + ULONG baInterfaceNr6; + ULONG baInterfaceNr7; +} UX_DEVICE_CLASS_AUDIO10_AC_HEADER7_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO10_AC_HEADER8_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bcdADC; + ULONG wTotalLength; + ULONG bInCollection; + ULONG baInterfaceNr1; + ULONG baInterfaceNr2; + ULONG baInterfaceNr3; + ULONG baInterfaceNr4; + ULONG baInterfaceNr5; + ULONG baInterfaceNr6; + ULONG baInterfaceNr7; + ULONG baInterfaceNr8; +} UX_DEVICE_CLASS_AUDIO10_AC_HEADER8_DESCRIPTOR; + + +/* Define Audio Class specific input terminal interface descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO10_AC_INPUT_TERMINAL_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bTerminalID; + ULONG wTerminalType; + ULONG bAssocTerminal; + ULONG bNrChannels; + ULONG wChannelConfig; + ULONG iChannelNames; + ULONG iTerminal; +} UX_DEVICE_CLASS_AUDIO10_AC_INPUT_TERMINAL_DESCRIPTOR; + + +/* Define Audio Class specific output terminal interface descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO10_AC_OUTPUT_TERMINAL_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bTerminalID; + ULONG wTerminalType; + ULONG bAssocTerminal; + ULONG bSourceID; + ULONG iTerminal; +} UX_DEVICE_CLASS_AUDIO10_AC_OUTPUT_TERMINAL_DESCRIPTOR; + + +/* Define Audio Class specific feature unit descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO10_AC_FEATURE_UNIT_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bUnitID; + ULONG bSourceID; + ULONG bControlSize; + ULONG bmaControls; +} UX_DEVICE_CLASS_AUDIO10_AC_FEATURE_UNIT_DESCRIPTOR; + + +/* Define Audio Class streaming interface descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO10_AS_INTERFACE_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bTerminalLink; + ULONG bDelay; + ULONG wFormatTag; +} UX_DEVICE_CLASS_AUDIO10_AS_INTERFACE_DESCRIPTOR; + + +/* Define Audio Class type I format type descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO10_AS_TYPE_I_FORMAT_TYPE_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bFormatType; + ULONG bNrChannels; + ULONG bSubframeSize; + ULONG bBitResolution; + ULONG bSamFreqType; + ULONG SamplingFrequency; +} UX_DEVICE_CLASS_AUDIO10_AS_TYPE_I_FORMAT_TYPE_DESCRIPTOR; + +#define UX_DEVICE_CLASS_AUDIO_AS_TYPE_I_FORMAT_TYPE_DESCRIPTOR_FORMAT_TYPE 3 +#define UX_DEVICE_CLASS_AUDIO_AS_TYPE_I_FORMAT_TYPE_DESCRIPTOR_NR_CHANNELS 4 +#define UX_DEVICE_CLASS_AUDIO_AS_TYPE_I_FORMAT_TYPE_DESCRIPTOR_SUBFRAME_SIZE 5 +#define UX_DEVICE_CLASS_AUDIO_AS_TYPE_I_FORMAT_TYPE_DESCRIPTOR_BIT_RESOLUTION 6 +#define UX_DEVICE_CLASS_AUDIO_AS_TYPE_I_FORMAT_TYPE_DESCRIPTOR_SAM_FREQ_TYPE 7 +#define UX_DEVICE_CLASS_AUDIO_AS_TYPE_I_FORMAT_TYPE_DESCRIPTOR_SAM_FREQ_TABLE 8 + + +/* Define Audio Class specific streaming endpoint descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO10_AS_ENDPOINT_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bmAttributes; + ULONG wMaxPacketSize; + ULONG bInterval; + ULONG bRefresh; + ULONG bSynchAddress; +} UX_DEVICE_CLASS_AUDIO10_AS_ENDPOINT_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO10_AS_DATA_ENDPOINT_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bmAttributes; + ULONG bLockDelayUnits; + ULONG wLockDelay; +} UX_DEVICE_CLASS_AUDIO10_AS_DATA_ENDPOINT_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO10_CONTROL_STRUCT +{ + ULONG ux_device_class_audio10_control_fu_id; + + ULONG ux_device_class_audio10_control_changed; + + USHORT ux_device_class_audio10_control_mute[1]; + SHORT ux_device_class_audio10_control_volume_min[1]; + SHORT ux_device_class_audio10_control_volume_max[1]; + SHORT ux_device_class_audio10_control_volume[1]; +} UX_DEVICE_CLASS_AUDIO10_CONTROL; + +#define UX_DEVICE_CLASS_AUDIO10_CONTROL_MUTE_CHANGED 1 +#define UX_DEVICE_CLASS_AUDIO10_CONTROL_VOLUME_CHANGED 2 + +typedef struct UX_DEVICE_CLASS_AUDIO10_CONTROL_GROUP_STRUCT +{ + ULONG ux_device_class_audio10_control_group_controls_nb; + UX_DEVICE_CLASS_AUDIO10_CONTROL *ux_device_class_audio10_control_group_controls; +} UX_DEVICE_CLASS_AUDIO10_CONTROL_GROUP; + +UINT _ux_device_class_audio10_control_process(UX_DEVICE_CLASS_AUDIO *audio, + UX_SLAVE_TRANSFER *transfer_request, + UX_DEVICE_CLASS_AUDIO10_CONTROL_GROUP *group); + +#define ux_device_class_audio10_control_process _ux_device_class_audio10_control_process + +#endif /* ifndef UX_DEVICE_CLASS_AUDIO10_H */ diff --git a/common/usbx_device_classes/inc/ux_device_class_audio20.h b/common/usbx_device_classes/inc/ux_device_class_audio20.h new file mode 100644 index 0000000..6da1b1b --- /dev/null +++ b/common/usbx_device_classes/inc/ux_device_class_audio20.h @@ -0,0 +1,418 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_audio20.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX audio class version 2.0. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_AUDIO20_H +#define UX_DEVICE_CLASS_AUDIO20_H + + +/* Define Audio Class function category codes. */ + +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_DESKTOP_SPEAKER 0x01 +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_HOME_THEATER 0x02 +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_MICROPHONE 0x03 +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_HEADSET 0x04 +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_TELEPHONE 0x05 +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_CONVERTER 0x06 +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_VOICE_SOUND_RECORDER 0x07 +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_I_O_BOX 0x08 +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_MUSICAL_INSTRUMENT 0x09 +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_PRO_AUDIO 0x0A +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_AUDIO_VIDEO 0x0B +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_CONTROL_PANEL 0x0C +#define UX_DEVICE_CLASS_AUDIO20_CATEGORY_OTHER 0xFF + + +/* Define Audio Class specific AC interface descriptor subclasses. */ + +#define UX_DEVICE_CLASS_AUDIO20_AC_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO20_AC_HEADER 0x01 +#define UX_DEVICE_CLASS_AUDIO20_AC_INPUT_TERMINAL 0x02 +#define UX_DEVICE_CLASS_AUDIO20_AC_OUTPUT_TERMINAL 0x03 +#define UX_DEVICE_CLASS_AUDIO20_AC_MIXER_UNIT 0x04 +#define UX_DEVICE_CLASS_AUDIO20_AC_SELECTOR_UNIT 0x05 +#define UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT 0x06 +#define UX_DEVICE_CLASS_AUDIO20_AC_EFFECT_UNIT 0x07 +#define UX_DEVICE_CLASS_AUDIO20_AC_PROCESSING_UNIT 0x08 +#define UX_DEVICE_CLASS_AUDIO20_AC_EXTENSION_UNIT 0x09 +#define UX_DEVICE_CLASS_AUDIO20_AC_CLOCK_SOURCE 0x0A +#define UX_DEVICE_CLASS_AUDIO20_AC_CLOCK_SELECTOR 0x0B +#define UX_DEVICE_CLASS_AUDIO20_AC_CLOCK_MULTIPLIER 0x0C +#define UX_DEVICE_CLASS_AUDIO20_AC_SAMPLE_RATE_CONVERTER 0x0D + + +/* Define Audio Class specific AS interface descriptor subclasses. */ + +#define UX_DEVICE_CLASS_AUDIO20_AS_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO20_AS_GENERAL 0x01 +#define UX_DEVICE_CLASS_AUDIO20_AS_FORMAT_TYPE 0x02 +#define UX_DEVICE_CLASS_AUDIO20_AS_ENCODER 0x03 +#define UX_DEVICE_CLASS_AUDIO20_AS_DECODER 0x04 + + +/* Define Audio Class specific endpoint descriptor subtypes. */ + +#define UX_DEVICE_CLASS_AUDIO20_EP_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO20_EP_GENERAL 0x01 + + +/* Define Audio Class specific request codes. */ + +#define UX_DEVICE_CLASS_AUDIO20_REQUEST_CODE_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO20_CUR 0x01 +#define UX_DEVICE_CLASS_AUDIO20_RANGE 0x02 +#define UX_DEVICE_CLASS_AUDIO20_MEM 0x03 + + +/* Define Audio Class specific clock source control selectors. */ + +#define UX_DEVICE_CLASS_AUDIO20_CS_CONTROL_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO20_CS_SAM_FREQ_CONTROL 0x01 +#define UX_DEVICE_CLASS_AUDIO20_CS_CLOCK_VALID_CONTROL 0x02 + + +/* Define Audio Class specific clock selector control selectors. */ + + +#define UX_DEVICE_CLASS_AUDIO20_CX_CONTROL_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO20_CX_CLOCK_SELECTOR_CONTROL 0x01 + +/* Define Audio Class specific terminal control selectors. */ + +#define UX_DEVICE_CLASS_AUDIO20_TE_CONTROL_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO20_TE_COPY_PROTECT_CONTROL 0x01 +#define UX_DEVICE_CLASS_AUDIO20_TE_CONNECTOR_CONTROL 0x02 +#define UX_DEVICE_CLASS_AUDIO20_TE_OVERLOAD_CONTROL 0x03 +#define UX_DEVICE_CLASS_AUDIO20_TE_CLUSTER_CONTROL 0x04 +#define UX_DEVICE_CLASS_AUDIO20_TE_UNDERFLOW_CONTROL 0x05 +#define UX_DEVICE_CLASS_AUDIO20_TE_OVERFLOW_CONTROL 0x06 +#define UX_DEVICE_CLASS_AUDIO20_TE_LATENCY_CONTROL 0x07 + + +/* Define Audio Class specific feature unit control selectors. */ + +#define UX_DEVICE_CLASS_AUDIO20_FU_CONTROL_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_AUDIO20_FU_MUTE_CONTROL 0x01 +#define UX_DEVICE_CLASS_AUDIO20_FU_VOLUME_CONTROL 0x02 +#define UX_DEVICE_CLASS_AUDIO20_FU_BASS_CONTROL 0x03 +#define UX_DEVICE_CLASS_AUDIO20_FU_MID_CONTROL 0x04 +#define UX_DEVICE_CLASS_AUDIO20_FU_TREBLE_CONTROL 0x05 +#define UX_DEVICE_CLASS_AUDIO20_FU_GRAPHIC_EQUALIZER_CONTROL 0x06 +#define UX_DEVICE_CLASS_AUDIO20_FU_AUTOMATIC_GAIN_CONTROL 0x07 +#define UX_DEVICE_CLASS_AUDIO20_FU_DELAY_CONTROL 0x08 +#define UX_DEVICE_CLASS_AUDIO20_FU_BASS_BOOST_CONTROL 0x09 +#define UX_DEVICE_CLASS_AUDIO20_FU_LOUNDNESS_CONTROL 0x0A +#define UX_DEVICE_CLASS_AUDIO20_FU_INPUT_GAIN_CONTROL 0x0B +#define UX_DEVICE_CLASS_AUDIO20_FU_INPUT_GAIN_PAD_CONTROL 0x0C +#define UX_DEVICE_CLASS_AUDIO20_FU_PHASE_INVERTER_CONTROL 0x0D +#define UX_DEVICE_CLASS_AUDIO20_FU_UNDERFLOW_CONTROL 0x0E +#define UX_DEVICE_CLASS_AUDIO20_FU_OVERFLOW_CONTROL 0x0F +#define UX_DEVICE_CLASS_AUDIO20_FU_LATENCY_CONTROL 0x10 + + +/* Define Audio Class encoding format type bit allocations. */ + +#define UX_DEVICE_CLASS_AUDIO20_FORMAT_PCM (1u << 0) +#define UX_DEVICE_CLASS_AUDIO20_FORMAT_PCM8 (1u << 1) +#define UX_DEVICE_CLASS_AUDIO20_FORMAT_IEEE_FLOAT (1u << 2) +#define UX_DEVICE_CLASS_AUDIO20_FORMAT_ALAW (1u << 3) +#define UX_DEVICE_CLASS_AUDIO20_FORMAT_MULAW (1u << 4) +#define UX_DEVICE_CLASS_AUDIO20_FORMAT_RAW (1u << 31) + + +/* Audio Class Control header descriptor structures. */ + +typedef struct UX_DEVICE_CLASS_AUDIO20_AC_HEADER_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bcdADC; + ULONG bCategory; + ULONG wTotalLength; + ULONG bmControls; +} UX_DEVICE_CLASS_AUDIO20_AC_HEADER_DESCRIPTOR; + + +/* Define Audio Class specific clock source descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO20_AC_CLOCK_SOURCE_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bClockID; + ULONG bmAttributes; + ULONG bmControls; + ULONG bAssocTerminal; + ULONG iClockSource; +} UX_DEVICE_CLASS_AUDIO20_AC_CLOCK_SOURCE_DESCRIPTOR; + + +/* Define Audio Class specific input terminal interface descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO20_AC_INPUT_TERMINAL_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bTerminalID; + ULONG wTerminalType; + ULONG bAssocTerminal; + ULONG bCSourceID; + ULONG bNrChannels; + ULONG bmChannelConfig; + ULONG iChannelNames; + ULONG bmControls; + ULONG iTerminal; +} UX_DEVICE_CLASS_AUDIO20_AC_INPUT_TERMINAL_DESCRIPTOR; + + +/* Define Audio Class specific output terminal interface descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO20_AC_OUTPUT_TERMINAL_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bTerminalID; + ULONG wTerminalType; + ULONG bAssocTerminal; + ULONG bSourceID; + ULONG bCSourceID; + ULONG bmControls; + ULONG iTerminal; +} UX_DEVICE_CLASS_AUDIO20_AC_OUTPUT_TERMINAL_DESCRIPTOR; + + +/* Define Audio Class specific feature unit descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bUnitID; + ULONG bSourceID; + ULONG bmaControls; +} UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT1_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bUnitID; + ULONG bSourceID; + ULONG bmaControls0; + ULONG bmaControls1; +} UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT1_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT2_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bUnitID; + ULONG bSourceID; + ULONG bmaControls0; + ULONG bmaControls1; + ULONG bmaControls2; +} UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT2_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT3_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bUnitID; + ULONG bSourceID; + ULONG bmaControls0; + ULONG bmaControls1; + ULONG bmaControls2; + ULONG bmaControls3; +} UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT3_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT6_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bUnitID; + ULONG bSourceID; + ULONG bmaControls0; + ULONG bmaControls1; + ULONG bmaControls2; + ULONG bmaControls3; + ULONG bmaControls4; + ULONG bmaControls5; + ULONG bmaControls6; +} UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT6_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT7_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bUnitID; + ULONG bSourceID; + ULONG bmaControls0; + ULONG bmaControls1; + ULONG bmaControls2; + ULONG bmaControls3; + ULONG bmaControls4; + ULONG bmaControls5; + ULONG bmaControls6; + ULONG bmaControls7; +} UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT7_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT8_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bUnitID; + ULONG bSourceID; + ULONG bmaControls0; + ULONG bmaControls1; + ULONG bmaControls2; + ULONG bmaControls3; + ULONG bmaControls4; + ULONG bmaControls5; + ULONG bmaControls6; + ULONG bmaControls7; + ULONG bmaControls8; +} UX_DEVICE_CLASS_AUDIO20_AC_FEATURE_UNIT8_DESCRIPTOR; + + +/* Define Audio Class streaming interface descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO20_AS_INTERFACE_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bTerminalLink; + ULONG bmControls; + ULONG bFormatType; + ULONG bmFormats; + ULONG bNrChannels; + ULONG bmChannelConfig; + ULONG iChannelNames; +} UX_DEVICE_CLASS_AUDIO20_AS_INTERFACE_DESCRIPTOR; + + +/* Define Audio Class type I format type descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO20_AS_TYPE_I_FORMAT_TYPE_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bFormatType; + ULONG bSubslotSize; + ULONG bBitResolution; +} UX_DEVICE_CLASS_AUDIO20_AS_TYPE_I_FORMAT_TYPE_DESCRIPTOR; + + +/* Define Audio Class specific streaming endpoint descriptor. */ + +typedef struct UX_DEVICE_CLASS_AUDIO20_AS_DATA_ENDPOINT_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bmAttributes; + ULONG bmControls; + ULONG bLockDelayUnits; + ULONG wLockDelay; +} UX_DEVICE_CLASS_AUDIO20_AS_DATA_ENDPOINT_DESCRIPTOR; + +typedef struct UX_DEVICE_CLASS_AUDIO20_CONTROL_STRUCT +{ + ULONG ux_device_class_audio20_control_cs_id; + ULONG ux_device_class_audio20_control_fu_id; + ULONG ux_device_class_audio20_control_sampling_frequency; + + ULONG ux_device_class_audio20_control_changed; + + USHORT ux_device_class_audio20_control_mute[1]; + SHORT ux_device_class_audio20_control_volume_min[1]; + SHORT ux_device_class_audio20_control_volume_max[1]; + SHORT ux_device_class_audio20_control_volume[1]; +} UX_DEVICE_CLASS_AUDIO20_CONTROL; + +#define UX_DEVICE_CLASS_AUDIO20_CONTROL_MUTE_CHANGED 1 +#define UX_DEVICE_CLASS_AUDIO20_CONTROL_VOLUME_CHANGED 2 + +typedef struct UX_DEVICE_CLASS_AUDIO20_CONTROL_GROUP_STRUCT +{ + ULONG ux_device_class_audio20_control_group_controls_nb; + UX_DEVICE_CLASS_AUDIO20_CONTROL *ux_device_class_audio20_control_group_controls; +} UX_DEVICE_CLASS_AUDIO20_CONTROL_GROUP; + + +UINT _ux_device_class_audio20_control_process(UX_DEVICE_CLASS_AUDIO *audio, + UX_SLAVE_TRANSFER *transfer, + UX_DEVICE_CLASS_AUDIO20_CONTROL_GROUP *group); + +#define ux_device_class_audio20_control_process _ux_device_class_audio20_control_process + +#endif /* ifndef UX_DEVICE_CLASS_AUDIO20_H */ diff --git a/common/usbx_device_classes/inc/ux_device_class_cdc_acm.h b/common/usbx_device_classes/inc/ux_device_class_cdc_acm.h new file mode 100644 index 0000000..43a6703 --- /dev/null +++ b/common/usbx_device_classes/inc/ux_device_class_cdc_acm.h @@ -0,0 +1,259 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_cdc_acm.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the equivalences for the USBX Device Class CDC */ +/* ACM component. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_CDC_ACM_H +#define UX_DEVICE_CLASS_CDC_ACM_H + + +/* Define CDC Class USB Class constants. */ +#define UX_SLAVE_CLASS_CDC_ACM_CLASS 10 + +/* Device CDC Requests */ +#define UX_SLAVE_CLASS_CDC_ACM_SEND_ENCAPSULATED_COMMAND 0x00 +#define UX_SLAVE_CLASS_CDC_ACM_GET_ENCAPSULATED_RESPONSE 0x01 +#define UX_SLAVE_CLASS_CDC_ACM_SET_COMM_FEATURE 0x02 +#define UX_SLAVE_CLASS_CDC_ACM_GET_COMM_FEATURE 0x03 +#define UX_SLAVE_CLASS_CDC_ACM_CLEAR_COMM_FEATURE 0x04 +#define UX_SLAVE_CLASS_CDC_ACM_SET_AUX_LINE_STATE 0x10 +#define UX_SLAVE_CLASS_CDC_ACM_SET_HOOK_STATE 0x11 +#define UX_SLAVE_CLASS_CDC_ACM_PULSE_SETUP 0x12 +#define UX_SLAVE_CLASS_CDC_ACM_SEND_PULSE 0x13 +#define UX_SLAVE_CLASS_CDC_ACM_SET_PULSE_TIME 0x14 +#define UX_SLAVE_CLASS_CDC_ACM_RING_AUX_JACK 0x15 +#define UX_SLAVE_CLASS_CDC_ACM_SET_LINE_CODING 0x20 +#define UX_SLAVE_CLASS_CDC_ACM_GET_LINE_CODING 0x21 +#define UX_SLAVE_CLASS_CDC_ACM_SET_CONTROL_LINE_STATE 0x22 +#define UX_SLAVE_CLASS_CDC_ACM_SEND_BREAK 0x23 +#define UX_SLAVE_CLASS_CDC_ACM_SET_RINGER_PARMS 0x30 +#define UX_SLAVE_CLASS_CDC_ACM_GET_RINGER_PARMS 0x31 +#define UX_SLAVE_CLASS_CDC_ACM_SET_OPERATION_PARMS 0x32 +#define UX_SLAVE_CLASS_CDC_ACM_GET_OPERATION_PARMS 0x33 +#define UX_SLAVE_CLASS_CDC_ACM_SET_LINE_PARMS 0x34 +#define UX_SLAVE_CLASS_CDC_ACM_GET_LINE_PARMS 0x35 +#define UX_SLAVE_CLASS_CDC_ACM_DIAL_DIGITS 0x36 +#define UX_SLAVE_CLASS_CDC_ACM_SET_UNIT_PARAMETER 0x37 +#define UX_SLAVE_CLASS_CDC_ACM_GET_UNIT_PARAMETER 0x38 +#define UX_SLAVE_CLASS_CDC_ACM_CLEAR_UNIT_PARAMETER 0x39 +#define UX_SLAVE_CLASS_CDC_ACM_GET_PROFILE 0x3A +#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_MULTICAST_FILTERS 0x40 +#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_POWER_MANAGEMENT_PATTERN 0x41 +#define UX_SLAVE_CLASS_CDC_ACM_GET_ETHERNET_POWER_MANAGEMENT_PATTERN 0x42 +#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_PACKET_FILTER 0x43 +#define UX_SLAVE_CLASS_CDC_ACM_GET_ETHERNET_STATISTIC 0x44 +#define UX_SLAVE_CLASS_CDC_ACM_SET_ATM_DATA_FORMAT 0x50 +#define UX_SLAVE_CLASS_CDC_ACM_GET_ATM_DEVICE_STATISTICS 0x51 +#define UX_SLAVE_CLASS_CDC_ACM_SET_ATM_DEFAULT_VC 0x52 +#define UX_SLAVE_CLASS_CDC_ACM_GET_ATM_VC_STATISTICS 0x53 + +/* Default line coding values. */ +#define UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_BAUDRATE 115200 +#define UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_STOP_BIT 1 +#define UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARITY 0 +#define UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_DATA_BIT 8 + +/* Define line coding structure. */ +#define UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_BAUDRATE_STRUCT 0 +#define UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_STOP_BIT_STRUCT 4 +#define UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARITY_STRUCT 5 +#define UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_DATA_BIT_STRUCT 6 +#define UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_RESPONSE_SIZE 7 + +/* Define line state bits. */ +#define UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_DTR 1 +#define UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_RTS 2 + +/* Define Transfer direction bits. */ +#define UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_XMIT 1 +#define UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_RCV 2 + +/* Define IOCTL functions. */ +#define UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING 1 +#define UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING 2 +#define UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_STATE 3 +#define UX_SLAVE_CLASS_CDC_ACM_IOCTL_ABORT_PIPE 4 +#define UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE 5 +#define UX_SLAVE_CLASS_CDC_ACM_IOCTL_TRANSMISSION_START 6 +#define UX_SLAVE_CLASS_CDC_ACM_IOCTL_TRANSMISSION_STOP 7 +#define UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_READ_TIMEOUT 8 +#define UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_WRITE_TIMEOUT 9 + +/* Define event group flag. */ +#define UX_DEVICE_CLASS_CDC_ACM_WRITE_EVENT 1 + +/* Define Slave CDC Class Calling Parameter structure */ + +typedef struct UX_SLAVE_CLASS_CDC_ACM_PARAMETER_STRUCT +{ + VOID (*ux_slave_class_cdc_acm_instance_activate)(VOID *); + VOID (*ux_slave_class_cdc_acm_instance_deactivate)(VOID *); + VOID (*ux_slave_class_cdc_acm_parameter_change)(VOID *); + +} UX_SLAVE_CLASS_CDC_ACM_PARAMETER; + +/* Define CDC Class structure. */ + +typedef struct UX_SLAVE_CLASS_CDC_ACM_STRUCT +{ + UX_SLAVE_INTERFACE *ux_slave_class_cdc_acm_interface; + UX_SLAVE_CLASS_CDC_ACM_PARAMETER ux_slave_class_cdc_acm_parameter; + TX_MUTEX ux_slave_class_cdc_acm_endpoint_in_mutex; + TX_MUTEX ux_slave_class_cdc_acm_endpoint_out_mutex; + ULONG ux_slave_class_cdc_acm_baudrate; + UCHAR ux_slave_class_cdc_acm_stop_bit; + UCHAR ux_slave_class_cdc_acm_parity; + UCHAR ux_slave_class_cdc_acm_data_bit; + UCHAR ux_slave_class_cdc_acm_data_dtr_state; + UCHAR ux_slave_class_cdc_acm_data_rts_state; + TX_THREAD ux_slave_class_cdc_acm_bulkin_thread; + TX_THREAD ux_slave_class_cdc_acm_bulkout_thread; + UCHAR *ux_slave_class_cdc_acm_bulkin_thread_stack; + UCHAR *ux_slave_class_cdc_acm_bulkout_thread_stack; + UINT (*ux_device_class_cdc_acm_write_callback)(struct UX_SLAVE_CLASS_CDC_ACM_STRUCT *cdc_acm, UINT status, ULONG length); + UINT (*ux_device_class_cdc_acm_read_callback)(struct UX_SLAVE_CLASS_CDC_ACM_STRUCT *cdc_acm, UINT status, UCHAR *data_pointer, ULONG length); + TX_EVENT_FLAGS_GROUP ux_slave_class_cdc_acm_event_flags_group; + ULONG ux_slave_class_cdc_acm_transmission_status; + ULONG ux_slave_class_cdc_acm_scheduled_write; + ULONG ux_slave_class_cdc_acm_callback_total_length; + UCHAR *ux_slave_class_cdc_acm_callback_data_pointer; + UCHAR *ux_slave_class_cdc_acm_callback_current_data_pointer; + +} UX_SLAVE_CLASS_CDC_ACM; + +/* Define some CDC Class structures */ + +typedef struct UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARAMETER_STRUCT +{ + ULONG ux_slave_class_cdc_acm_parameter_baudrate; + UCHAR ux_slave_class_cdc_acm_parameter_stop_bit; + UCHAR ux_slave_class_cdc_acm_parameter_parity; + UCHAR ux_slave_class_cdc_acm_parameter_data_bit; + +} UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARAMETER; + +typedef struct UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER_STRUCT +{ + UCHAR ux_slave_class_cdc_acm_parameter_rts; + UCHAR ux_slave_class_cdc_acm_parameter_dtr; + +} UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER; + +typedef struct UX_SLAVE_CLASS_CDC_ACM_CALLBACK_PARAMETER_STRUCT +{ + UINT (*ux_device_class_cdc_acm_parameter_write_callback)(struct UX_SLAVE_CLASS_CDC_ACM_STRUCT *cdc_acm, UINT status, ULONG length); + UINT (*ux_device_class_cdc_acm_parameter_read_callback)(struct UX_SLAVE_CLASS_CDC_ACM_STRUCT *cdc_acm, UINT status, UCHAR *data_pointer, ULONG length); + +} UX_SLAVE_CLASS_CDC_ACM_CALLBACK_PARAMETER; + + + +/* Requests - Ethernet Networking Control Model */ + +#define UX_SLAVE_CLASS_CDC_ACM_SEND_ENCAPSULATED_COMMAND 0x00 + /* Issues a command in the format of the supported control + protocol. The intent of this mechanism is to support + networking devices (e.g., host-based cable modems) + that require an additional vendor-defined interface for + media specific hardware configuration and + management. */ +#define UX_SLAVE_CLASS_CDC_ACM_GET_ENCAPSULATED_RESPONSE 0x01 + /* Requests a response in the format of the supported + control protocol. */ +#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_MULTICAST_FILTERS 0x40 + /* As applications are loaded and unloaded on the host, + the networking transport will instruct the device's MAC + driver to change settings of the Networking device's + multicast filters. */ +#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x41 + /* Some hosts are able to conserve energy and stay quiet + in a 'sleeping' state while not being used. USB + Networking devices may provide special pattern filtering + hardware that enables it to wake up the attached host + on demand when something is attempting to contact the + host (e.g., an incoming web browser connection). + Primitives are needed in management plane to negotiate + the setting of these special filters */ +#define UX_SLAVE_CLASS_CDC_ACM_GET_ETHERNET_POWER_MANAGEMENT_PATTERN_FILTER 0x42 + /* Retrieves the status of the above power management + pattern filter setting */ +#define UX_SLAVE_CLASS_CDC_ACM_SET_ETHERNET_PACKET_FILTER 0x43 + /* Sets device filter for running a network analyzer + application on the host machine */ +#define UX_SLAVE_CLASS_CDC_ACM_GET_ETHERNET_STATISTIC 0x44 + /* Retrieves Ethernet device statistics such as frames + transmitted, frames received, and bad frames received. */ + +/* Define buffer length for IN/OUT pipes. */ + +#define UX_SLAVE_CLASS_CDC_ACM_BUFFER_SIZE 4096 + + +/* Define Device CDC Class prototypes. */ + +UINT _ux_device_class_cdc_acm_activate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_acm_control_request(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_acm_deactivate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_acm_entry(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_acm_initialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_acm_uninitialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_acm_write(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_device_class_cdc_acm_read(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_device_class_cdc_acm_ioctl(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, ULONG ioctl_function, + VOID *parameter); +VOID _ux_device_class_cdc_acm_bulkin_thread(ULONG class_pointer); +VOID _ux_device_class_cdc_acm_bulkout_thread(ULONG class_pointer); +UINT _ux_device_class_cdc_acm_write_with_callback(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, + ULONG requested_length); + + +/* Define Device CDC Class API prototypes. */ + +#define ux_device_class_cdc_acm_entry _ux_device_class_cdc_acm_entry +#define ux_device_class_cdc_acm_read _ux_device_class_cdc_acm_read +#define ux_device_class_cdc_acm_write _ux_device_class_cdc_acm_write +#define ux_device_class_cdc_acm_ioctl _ux_device_class_cdc_acm_ioctl +#define ux_device_class_cdc_acm_write_with_callback _ux_device_class_cdc_acm_write_with_callback + +#endif /* UX_DEVICE_CLASS_CDC_ACM_H */ diff --git a/common/usbx_device_classes/inc/ux_device_class_cdc_ecm.h b/common/usbx_device_classes/inc/ux_device_class_cdc_ecm.h new file mode 100644 index 0000000..df6dee3 --- /dev/null +++ b/common/usbx_device_classes/inc/ux_device_class_cdc_ecm.h @@ -0,0 +1,337 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_cdc_ecm.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the equivalences for the USBX Device Class */ +/* CDC_ECM component. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_CDC_ECM_H +#define UX_DEVICE_CLASS_CDC_ECM_H + +#include "nx_api.h" +#include "ux_network_driver.h" + +/* Define generic CDC_ECM equivalences. */ +#define UX_DEVICE_CLASS_CDC_ECM_CLASS_COMMUNICATION_CONTROL 0x02 +#define UX_DEVICE_CLASS_CDC_ECM_SUBCLASS_COMMUNICATION_CONTROL 0x06 +#define UX_DEVICE_CLASS_CDC_ECM_CLASS_COMMUNICATION_DATA 0x0A +#define UX_DEVICE_CLASS_CDC_ECM_NEW_INTERRUPT_EVENT 0x01 +#define UX_DEVICE_CLASS_CDC_ECM_NEW_BULKOUT_EVENT 0x02 +#define UX_DEVICE_CLASS_CDC_ECM_NEW_BULKIN_EVENT 0x04 +#define UX_DEVICE_CLASS_CDC_ECM_NEW_DEVICE_STATE_CHANGE_EVENT 0x08 +#define UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT 0x10 +#define UX_DEVICE_CLASS_CDC_ECM_INTERRUPT_RESPONSE_LENGTH 8 +#define UX_DEVICE_CLASS_CDC_ECM_MAX_CONTROL_RESPONSE_LENGTH 256 +#define UX_DEVICE_CLASS_CDC_ECM_INTERRUPT_RESPONSE_AVAILABLE_FLAG 1 +#define UX_DEVICE_CLASS_CDC_ECM_BASE_IP_ADDRESS 0xC0A80001 +#define UX_DEVICE_CLASS_CDC_ECM_BASE_IP_MASK 0xFFFFFF00 +#define UX_DEVICE_CLASS_CDC_ECM_MAX_MTU 1518 +#define UX_DEVICE_CLASS_CDC_ECM_ETHERNET_IP 0x0800 +#define UX_DEVICE_CLASS_CDC_ECM_ETHERNET_ARP 0x0806 +#define UX_DEVICE_CLASS_CDC_ECM_ETHERNET_RARP 0x8035 +#define UX_DEVICE_CLASS_CDC_ECM_ETHERNET_PACKET_SIZE 1536 +#define UX_DEVICE_CLASS_CDC_ECM_NX_ALIGN_PADDING 2 +#ifndef UX_DEVICE_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES +#define UX_DEVICE_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES 16 +#endif + +#define UX_DEVICE_CLASS_CDC_ECM_NX_PACKET_SIZE sizeof(NX_PACKET) + +#define UX_DEVICE_CLASS_CDC_ECM_NX_PAYLOAD_SIZE_ASSERT UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG(UX_DEVICE_CLASS_CDC_ECM_ETHERNET_PACKET_SIZE, UX_DEVICE_CLASS_CDC_ECM_NX_ALIGN_PADDING), UX_DEVICE_CLASS_CDC_ECM_NX_PAYLOAD_SIZE_calc_ovf) +#define UX_DEVICE_CLASS_CDC_ECM_NX_PAYLOAD_SIZE (UX_DEVICE_CLASS_CDC_ECM_ETHERNET_PACKET_SIZE + UX_DEVICE_CLASS_CDC_ECM_NX_ALIGN_PADDING) + +#define UX_DEVICE_CLASS_CDC_ECM_NX_BUFF_SIZE_ASSERT \ + UX_DEVICE_CLASS_CDC_ECM_NX_PAYLOAD_SIZE_ASSERT \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG( \ + UX_DEVICE_CLASS_CDC_ECM_NX_PAYLOAD_SIZE, \ + UX_DEVICE_CLASS_CDC_ECM_NX_PACKET_SIZE), \ + UX_DEVICE_CLASS_CDC_ECM_NX_BUFF_SIZE_calc_ovf) +#define UX_DEVICE_CLASS_CDC_ECM_NX_BUFF_SIZE (UX_DEVICE_CLASS_CDC_ECM_NX_PAYLOAD_SIZE + UX_DEVICE_CLASS_CDC_ECM_NX_PACKET_SIZE) + +#define UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT \ + UX_DEVICE_CLASS_CDC_ECM_NX_BUFF_SIZE_ASSERT \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG( \ + UX_DEVICE_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES, \ + UX_DEVICE_CLASS_CDC_ECM_NX_BUFF_SIZE), \ + UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_calc1_ovf) \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG( \ + UX_DEVICE_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES * \ + UX_DEVICE_CLASS_CDC_ECM_NX_BUFF_SIZE, \ + 32), UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_calc2_ovf) +#define UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE (UX_DEVICE_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES * UX_DEVICE_CLASS_CDC_ECM_NX_BUFF_SIZE + 32) + +#define UX_DEVICE_CLASS_CDC_ECM_ETHERNET_SIZE 14 +#define UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH 6 +#define UX_DEVICE_CLASS_CDC_ECM_VENDOR_DESCRIPTION_MAX_LENGTH 64 +#define UX_DEVICE_CLASS_CDC_ECM_MAC_OPTIONS 8 +#define UX_DEVICE_CLASS_CDC_ECM_PACKET_HEADER_MSG 1 + +/* Device CDC_ECM Requests */ +#define UX_DEVICE_CLASS_CDC_ECM_SEND_ENCAPSULATED_COMMAND 0x00 +#define UX_DEVICE_CLASS_CDC_ECM_GET_ENCAPSULATED_RESPONSE 0x01 +#define UX_DEVICE_CLASS_CDC_ECM_SET_ETHERNET_MULTICAST_FILTER 0x40 +#define UX_DEVICE_CLASS_CDC_ECM_SET_ETHERNET_POWER_MANAGEMENT_FILTER 0x41 +#define UX_DEVICE_CLASS_CDC_ECM_GET_ETHERNET_POWER_MANAGEMENT_FILTER 0x42 +#define UX_DEVICE_CLASS_CDC_ECM_SET_ETHERNET_PACKET_FILTER 0x43 + +/* Define CDC_ECM Versions. Set to 1.0 here. */ +#define UX_DEVICE_CLASS_CDC_ECM_VERSION_MAJOR 0x00000001 +#define UX_DEVICE_CLASS_CDC_ECM_VERSION_MINOR 0x00000000 + +/* Define CDC_ECM Conection type supported. Set to conectionless. */ +#define UX_DEVICE_CLASS_CDC_ECM_DF_CONNECTIONLESS 0x00000001 +#define UX_DEVICE_CLASS_CDC_ECM_DF_CONNECTION_ORIENTED 0x00000002 +#define UX_DEVICE_CLASS_CDC_ECM_DF_CONNECTION_SUPPORTED UX_DEVICE_CLASS_CDC_ECM_DF_CONNECTIONLESS + +/* Define CDC_ECM Medium supported by the device. */ +#define UX_DEVICE_CLASS_CDC_ECM_MEDIUM_SUPPORTED 0x00000000 + +/* Define CDC_ECM Packet size and types supported. */ +#define UX_DEVICE_CLASS_CDC_ECM_MAX_PACKET_PER_TRANSFER 0x00000001 +#define UX_DEVICE_CLASS_CDC_ECM_MAX_PACKET_TRANSFER_SIZE 0x00000640 +#define UX_DEVICE_CLASS_CDC_ECM_PACKET_ALIGNEMENT_FACTOR 0x00000003 +#define UX_DEVICE_CLASS_CDC_ECM_MAX_FRAME_SIZE 0x000005DC +#define UX_DEVICE_CLASS_CDC_ECM_MAX_PACKET_LENGTH 0x000005EA + +/* Define LINK speeds. */ +#define UX_DEVICE_CLASS_CDC_ECM_LINK_SPEED_FS 0x0001D4C0 + +/* Define LINK statess. */ +#define UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_DOWN 0 +#define UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP 1 +#define UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_PENDING_UP 2 +#define UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_PENDING_DOWN 3 + +/* Define media connection values. */ +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_CONNECTED 0x00000000 +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_DISCONNECTED 0x00000001 + +/* Define media supported values. */ +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_802_3 0x00000000 +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_802_5 0x00000001 +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_FDDI 0x00000002 +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_WAN 0x00000003 +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_LOCAL_TALK 0x00000004 +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_DIX 0x00000005 +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_ARCNET_RAW 0x00000006 +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_ARCNET_878_2 0x00000007 +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_ATM 0x00000008 +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_WIRELESS_WAN 0x00000009 +#define UX_DEVICE_CLASS_CDC_ECM_MEDIA_IRDA 0x0000000A + +/* Define CDC_ECM status values. */ +#define UX_DEVICE_CLASS_CDC_ECM_STATUS_SUCCESS 0x00000000 +#define UX_DEVICE_CLASS_CDC_ECM_STATUS_FAILURE 0xC0000001 +#define UX_DEVICE_CLASS_CDC_ECM_STATUS_INVALID_DATA 0xC0010015 +#define UX_DEVICE_CLASS_CDC_ECM_STATUS_NOT_SUPPORTED 0xC00000BB +#define UX_DEVICE_CLASS_CDC_ECM_STATUS_MEDIA_CONNECTED 0x4001000B +#define UX_DEVICE_CLASS_CDC_ECM_STATUS_MEDIA_DISCONNECT 0x4001000C + +/* Define CDC_ECM Control Messages values. */ + +/* Define CDC_ECM State machine. */ +#define UX_DEVICE_CLASS_CDC_ECM_STATE_UNINITIALIZED 0x00000000 +#define UX_DEVICE_CLASS_CDC_ECM_STATE_INITIALIZED 0x00000001 +#define UX_DEVICE_CLASS_CDC_ECM_STATE_DATA_INITIALIZED 0x00000002 + +/* Define NetX errors inside the CDC_ECM class. */ +#define UX_DEVICE_CLASS_CDC_ECM_NX_SUCCESS 0x00 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NO_PACKET 0x01 +#define UX_DEVICE_CLASS_CDC_ECM_NX_UNDERFLOW 0x02 +#define UX_DEVICE_CLASS_CDC_ECM_NX_OVERFLOW 0x03 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NO_MAPPING 0x04 +#define UX_DEVICE_CLASS_CDC_ECM_NX_DELETED 0x05 +#define UX_DEVICE_CLASS_CDC_ECM_NX_POOL_ERROR 0x06 +#define UX_DEVICE_CLASS_CDC_ECM_NX_PTR_ERROR 0x07 +#define UX_DEVICE_CLASS_CDC_ECM_NX_WAIT_ERROR 0x08 +#define UX_DEVICE_CLASS_CDC_ECM_NX_SIZE_ERROR 0x09 +#define UX_DEVICE_CLASS_CDC_ECM_NX_OPTION_ERROR 0x0a +#define UX_DEVICE_CLASS_CDC_ECM_NX_DELETE_ERROR 0x10 +#define UX_DEVICE_CLASS_CDC_ECM_NX_CALLER_ERROR 0x11 +#define UX_DEVICE_CLASS_CDC_ECM_NX_INVALID_PACKET 0x12 +#define UX_DEVICE_CLASS_CDC_ECM_NX_INVALID_SOCKET 0x13 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NOT_ENABLED 0x14 +#define UX_DEVICE_CLASS_CDC_ECM_NX_ALREADY_ENABLED 0x15 +#define UX_DEVICE_CLASS_CDC_ECM_NX_ENTRY_NOT_FOUND 0x16 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NO_MORE_ENTRIES 0x17 +#define UX_DEVICE_CLASS_CDC_ECM_NX_ARP_TIMER_ERROR 0x18 +#define UX_DEVICE_CLASS_CDC_ECM_NX_RESERVED_CODE0 0x19 +#define UX_DEVICE_CLASS_CDC_ECM_NX_WAIT_ABORTED 0x1A +#define UX_DEVICE_CLASS_CDC_ECM_NX_IP_INTERNAL_ERROR 0x20 +#define UX_DEVICE_CLASS_CDC_ECM_NX_IP_ADDRESS_ERROR 0x21 +#define UX_DEVICE_CLASS_CDC_ECM_NX_ALREADY_BOUND 0x22 +#define UX_DEVICE_CLASS_CDC_ECM_NX_PORT_UNAVAILABLE 0x23 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NOT_BOUND 0x24 +#define UX_DEVICE_CLASS_CDC_ECM_NX_RESERVED_CODE1 0x25 +#define UX_DEVICE_CLASS_CDC_ECM_NX_SOCKET_UNBOUND 0x26 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NOT_CREATED 0x27 +#define UX_DEVICE_CLASS_CDC_ECM_NX_SOCKETS_BOUND 0x28 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NO_RESPONSE 0x29 +#define UX_DEVICE_CLASS_CDC_ECM_NX_POOL_DELETED 0x30 +#define UX_DEVICE_CLASS_CDC_ECM_NX_ALREADY_RELEASED 0x31 +#define UX_DEVICE_CLASS_CDC_ECM_NX_RESERVED_CODE2 0x32 +#define UX_DEVICE_CLASS_CDC_ECM_NX_MAX_LISTEN 0x33 +#define UX_DEVICE_CLASS_CDC_ECM_NX_DUPLICATE_LISTEN 0x34 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NOT_CLOSED 0x35 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NOT_LISTEN_STATE 0x36 +#define UX_DEVICE_CLASS_CDC_ECM_NX_IN_PROGRESS 0x37 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NOT_CONNECTED 0x38 +#define UX_DEVICE_CLASS_CDC_ECM_NX_WINDOW_OVERFLOW 0x39 +#define UX_DEVICE_CLASS_CDC_ECM_NX_ALREADY_SUSPENDED 0x40 +#define UX_DEVICE_CLASS_CDC_ECM_NX_DISCONNECT_FAILED 0x41 +#define UX_DEVICE_CLASS_CDC_ECM_NX_STILL_BOUND 0x42 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NOT_SUCCESSFUL 0x43 +#define UX_DEVICE_CLASS_CDC_ECM_NX_UNHANDLED_COMMAND 0x44 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NO_FREE_PORTS 0x45 +#define UX_DEVICE_CLASS_CDC_ECM_NX_INVALID_PORT 0x46 +#define UX_DEVICE_CLASS_CDC_ECM_NX_INVALID_RELISTEN 0x47 +#define UX_DEVICE_CLASS_CDC_ECM_NX_CONNECTION_PENDING 0x48 +#define UX_DEVICE_CLASS_CDC_ECM_NX_TX_QUEUE_DEPTH 0x49 +#define UX_DEVICE_CLASS_CDC_ECM_NX_NOT_IMPLEMENTED 0x80 + +/* Define timeout packet allocation value. */ +#ifndef UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT +#define UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT 1000 +#endif + +/* Define Slave CDC_ECM Class Calling Parameter structure */ + +typedef struct UX_SLAVE_CLASS_CDC_ECM_PARAMETER_STRUCT +{ + VOID (*ux_slave_class_cdc_ecm_instance_activate)(VOID *); + VOID (*ux_slave_class_cdc_ecm_instance_deactivate)(VOID *); + ULONG ux_slave_class_cdc_ecm_parameter_media; + ULONG ux_slave_class_cdc_ecm_parameter_vendor_id; + ULONG ux_slave_class_cdc_ecm_parameter_driver_version; + UCHAR ux_slave_class_cdc_ecm_parameter_vendor_description[UX_DEVICE_CLASS_CDC_ECM_VENDOR_DESCRIPTION_MAX_LENGTH]; + UCHAR ux_slave_class_cdc_ecm_parameter_local_node_id[UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH]; + UCHAR ux_slave_class_cdc_ecm_parameter_remote_node_id[UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH]; +} UX_SLAVE_CLASS_CDC_ECM_PARAMETER; + +/* Define CDC_ECM Class structure. */ + +typedef struct UX_SLAVE_CLASS_CDC_ECM_STRUCT +{ + UX_SLAVE_INTERFACE *ux_slave_class_cdc_ecm_interface; + UX_SLAVE_CLASS_CDC_ECM_PARAMETER ux_slave_class_cdc_ecm_parameter; + UX_SLAVE_ENDPOINT *ux_slave_class_cdc_ecm_bulkin_endpoint; + UX_SLAVE_ENDPOINT *ux_slave_class_cdc_ecm_bulkout_endpoint; + UX_SLAVE_ENDPOINT *ux_slave_class_cdc_ecm_interrupt_endpoint; + ULONG ux_slave_class_cdc_ecm_state; + ULONG ux_slave_class_cdc_ecm_current_alternate_setting; + ULONG ux_slave_class_cdc_ecm_max_transfer_size; + ULONG ux_slave_class_cdc_ecm_request_id; + ULONG ux_slave_class_cdc_ecm_statistics_xmit_ok; + ULONG ux_slave_class_cdc_ecm_statistics_rcv_ok; + ULONG ux_slave_class_cdc_ecm_statistics_xmit_error; + ULONG ux_slave_class_cdc_ecm_statistics_rcv_error; + ULONG ux_slave_class_cdc_ecm_statistics_rcv_no_buffer; + ULONG ux_slave_class_cdc_ecm_statistics_rcv_error_alignment; + ULONG ux_slave_class_cdc_ecm_statistics_xmit_one_collision; + ULONG ux_slave_class_cdc_ecm_statistics_xmit_more_collisions; + ULONG ux_slave_class_cdc_ecm_ethernet_multicast_filter; + ULONG ux_slave_class_cdc_ecm_ethernet_power_management_filter; + ULONG ux_slave_class_cdc_ecm_ethernet_packet_filter; + TX_EVENT_FLAGS_GROUP ux_slave_class_cdc_ecm_event_flags_group; + UCHAR ux_slave_class_cdc_ecm_local_node_id[UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH]; + UCHAR ux_slave_class_cdc_ecm_remote_node_id[UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH]; + NX_IP *ux_slave_class_cdc_ecm_nx_ip; + ULONG ux_slave_class_cdc_ecm_nx_ip_address; + ULONG ux_slave_class_cdc_ecm_nx_ip_network_mask; + NX_INTERFACE *ux_slave_class_cdc_ecm_nx_interface; + NX_PACKET *ux_slave_class_cdc_ecm_xmit_queue; + NX_PACKET *ux_slave_class_cdc_ecm_xmit_queue_tail; + NX_PACKET *ux_slave_class_cdc_ecm_receive_queue; + UCHAR *ux_slave_class_cdc_ecm_pool_memory; + NX_PACKET_POOL ux_slave_class_cdc_ecm_packet_pool; + TX_THREAD ux_slave_class_cdc_ecm_bulkin_thread; + TX_THREAD ux_slave_class_cdc_ecm_bulkout_thread; + TX_THREAD ux_slave_class_cdc_ecm_interrupt_thread; + UCHAR *ux_slave_class_cdc_ecm_bulkin_thread_stack; + UCHAR *ux_slave_class_cdc_ecm_bulkout_thread_stack; + UCHAR *ux_slave_class_cdc_ecm_interrupt_thread_stack; + ULONG ux_slave_class_cdc_ecm_link_state; + TX_MUTEX ux_slave_class_cdc_ecm_mutex; + VOID *ux_slave_class_cdc_ecm_network_handle; + +} UX_SLAVE_CLASS_CDC_ECM; + + +/* Requests - Ethernet Networking Control Model */ + +#define UX_DEVICE_CLASS_CDC_ECM_SEND_ENCAPSULATED_COMMAND 0x00 + /* Issues a command in the format of the supported control + protocol. The intent of this mechanism is to support + networking devices (e.g., host-based cable modems) + that require an additional vendor-defined interface for + media specific hardware configuration and + management. */ +#define UX_DEVICE_CLASS_CDC_ECM_GET_ENCAPSULATED_RESPONSE 0x01 + /* Requests a response in the format of the supported + control protocol. */ + + +/* Define buffer length for IN/OUT pipes. */ + +#define UX_DEVICE_CLASS_CDC_ECM_BUFFER_SIZE 4096 + + +/* Define Device CDC_ECM Class prototypes. */ + +UINT _ux_device_class_cdc_ecm_activate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_ecm_control_request(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_ecm_deactivate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_ecm_change(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_ecm_entry(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_ecm_initialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_ecm_uninitialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_cdc_ecm_write(VOID *cdc_ecm_class, NX_PACKET *packet); +VOID _ux_device_class_cdc_ecm_bulkin_thread(ULONG cdc_ecm_class); +VOID _ux_device_class_cdc_ecm_bulkout_thread(ULONG cdc_ecm_class); +VOID _ux_device_class_cdc_ecm_interrupt_thread(ULONG cdc_ecm_class); + + +/* Define Device CDC Class API prototypes. */ + +#define ux_device_class_cdc_ecm_entry _ux_device_class_cdc_ecm_entry +#define ux_device_class_cdc_ecm_read _ux_device_class_cdc_ecm_read +#define ux_device_class_cdc_ecm_write _ux_device_class_cdc_ecm_write + +#endif /* UX_DEVICE_CLASS_CDC_ECM_H */ diff --git a/common/usbx_device_classes/inc/ux_device_class_dfu.h b/common/usbx_device_classes/inc/ux_device_class_dfu.h new file mode 100644 index 0000000..815aec0 --- /dev/null +++ b/common/usbx_device_classes/inc/ux_device_class_dfu.h @@ -0,0 +1,183 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** DFU Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_dfu.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the equivalences for the USBX Device Class DFU */ +/* ACM component. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_DFU_H +#define UX_DEVICE_CLASS_DFU_H + +/* Define DFU class descriptor capabilities. */ +#define UX_SLAVE_CLASS_DFU_CAPABILITY_WILL_DETACH 0x08 +#define UX_SLAVE_CLASS_DFU_CAPABILITY_MANIFESTATION_TOLERANT 0x04 +#define UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_UPLOAD 0x02 +#define UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_DOWNLOAD 0x01 + +/* Define DFU Class USB Class constants. */ +#define UX_SLAVE_CLASS_DFU_CLASS 0xFE +#define UX_SLAVE_CLASS_DFU_SUBCLASS 0x01 +#define UX_SLAVE_CLASS_DFU_PROTOCOL_RUNTIME 0x01 +#define UX_SLAVE_CLASS_DFU_PROTOCOL_DFU_MODE 0x02 + +/* Define DFU MODES signals. */ +#define UX_DEVICE_CLASS_DFU_MODE_RUNTIME 1 +#define UX_DEVICE_CLASS_DFU_MODE_DFU 2 + + + + +/* Device DFU Requests */ +#define UX_SLAVE_CLASS_DFU_COMMAND_DETACH 0 +#define UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD 1 +#define UX_SLAVE_CLASS_DFU_COMMAND_UPLOAD 2 +#define UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS 3 +#define UX_SLAVE_CLASS_DFU_COMMAND_CLEAR_STATUS 4 +#define UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE 5 +#define UX_SLAVE_CLASS_DFU_COMMAND_ABORT 6 + +/* Device DFU Status values */ +#define UX_SLAVE_CLASS_DFU_STATUS_OK 0x00 +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_TARGET 0x01 +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_FILE 0x02 +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_WRITE 0x03 +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_ERASE 0x04 +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_CHECK_ERASED 0x05 +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_PROG 0x06 +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_VERIFY 0x07 +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_ADDRESS 0x08 +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_NOTDONE 0x09 +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_FIRMWARE 0x0A +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_VENDOR 0x0B +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_USBR 0x0C +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_POR 0x0D +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_UNKNOWN 0x0E +#define UX_SLAVE_CLASS_DFU_STATUS_ERROR_STALLEDPKT 0x0F + +#define UX_SLAVE_CLASS_DFU_STATUS_STATE_APP_IDLE 0 +#define UX_SLAVE_CLASS_DFU_STATUS_STATE_APP_DETACH 1 +#define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_IDLE 2 +#define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNLOAD_SYNC 3 +#define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNBUSY 4 +#define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNLOAD_IDLE 5 +#define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_SYNC 6 +#define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST 7 +#define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_WAIT_RESET 8 +#define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_UPLOAD_IDLE 9 +#define UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_ERROR 10 + +/* Define DFU class GET_STATUS command response. */ +#define UX_SLAVE_CLASS_DFU_GET_STATUS_STATUS 0 +#define UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT 1 +#define UX_SLAVE_CLASS_DFU_GET_STATUS_STATE 4 +#define UX_SLAVE_CLASS_DFU_GET_STATUS_STRING 5 +#define UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH 6 + +/* Define DFU class GET_STATE command response. */ +#define UX_SLAVE_CLASS_DFU_GET_STATE_STATE 0 +#define UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH 1 + +/* Define DFU application notification signals. */ +#define UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_DOWNLOAD 1 +#define UX_SLAVE_CLASS_DFU_NOTIFICATION_END_DOWNLOAD 2 +#define UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_DOWNLOAD 3 + +/* Define DFU application notification signals. */ +#define UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK 0 +#define UX_SLAVE_CLASS_DFU_MEDIA_STATUS_BUSY 1 +#define UX_SLAVE_CLASS_DFU_MEDIA_STATUS_ERROR 2 + +/* Define DFU thread event signals. */ +#define UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT 1 +#define UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET 2 + +/* Define Slave DFU Class Calling Parameter structure */ + +typedef struct UX_SLAVE_CLASS_DFU_PARAMETER_STRUCT +{ + + ULONG ux_slave_class_dfu_parameter_will_detach; + ULONG ux_slave_class_dfu_parameter_capabilities; + VOID (*ux_slave_class_dfu_parameter_instance_activate)(VOID *); + VOID (*ux_slave_class_dfu_parameter_instance_deactivate)(VOID *); + UINT (*ux_slave_class_dfu_parameter_read)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status); + UINT (*ux_slave_class_dfu_parameter_write)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status); + UINT (*ux_slave_class_dfu_parameter_get_status)(VOID *dfu, ULONG *media_status); + UINT (*ux_slave_class_dfu_parameter_notify)(VOID *dfu, ULONG notification); + UCHAR *ux_slave_class_dfu_parameter_framework; + ULONG ux_slave_class_dfu_parameter_framework_length; + +} UX_SLAVE_CLASS_DFU_PARAMETER; + +/* Define DFU Class structure. */ + +typedef struct UX_SLAVE_CLASS_DFU_STRUCT +{ + UX_SLAVE_INTERFACE *ux_slave_class_dfu_interface; + ULONG ux_slave_class_dfu_status; + ULONG ux_slave_class_dfu_state; + VOID (*ux_slave_class_dfu_instance_activate)(VOID *); + VOID (*ux_slave_class_dfu_instance_deactivate)(VOID *); + UINT (*ux_slave_class_dfu_read)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status); + UINT (*ux_slave_class_dfu_write)(VOID *dfu, ULONG block_number, UCHAR * data_pointer, ULONG length, ULONG *media_status); + UINT (*ux_slave_class_dfu_get_status)(VOID *dfu, ULONG *media_status); + UINT (*ux_slave_class_dfu_notify)(VOID *dfu, ULONG notification); + ULONG ux_slave_class_dfu_download_block_count; + ULONG ux_slave_class_dfu_upload_block_count; + TX_THREAD ux_slave_class_dfu_thread; + UCHAR *ux_slave_class_dfu_thread_stack; + TX_EVENT_FLAGS_GROUP ux_slave_class_dfu_event_flags_group; + +} UX_SLAVE_CLASS_DFU; + +/* Define Device DFU Class prototypes. */ + +UINT _ux_device_class_dfu_activate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_dfu_control_request(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_dfu_deactivate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_dfu_entry(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_dfu_initialize(UX_SLAVE_CLASS_COMMAND *command); +VOID _ux_device_class_dfu_thread(ULONG dfu_class); + +/* Define Device DFU Class API prototypes. */ + +#define ux_device_class_dfu_entry _ux_device_class_dfu_entry + +#endif /* UX_DEVICE_CLASS_DFU_H */ diff --git a/common/usbx_device_classes/inc/ux_device_class_hid.h b/common/usbx_device_classes/inc/ux_device_class_hid.h new file mode 100644 index 0000000..f1b885b --- /dev/null +++ b/common/usbx_device_classes/inc/ux_device_class_hid.h @@ -0,0 +1,180 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_hid.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX HID class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_HID_H +#define UX_DEVICE_CLASS_HID_H + +/* Define HID Class constants. */ + +#define UX_DEVICE_CLASS_HID_CLASS 0x03 +#define UX_DEVICE_CLASS_HID_SUBCLASS 0X00 +#define UX_DEVICE_CLASS_HID_PROTOCOL 0X00 + +/* Define HID Class commands. */ + +#define UX_DEVICE_CLASS_HID_COMMAND_GET_REPORT 0x01 +#define UX_DEVICE_CLASS_HID_COMMAND_GET_IDLE 0x02 +#define UX_DEVICE_CLASS_HID_COMMAND_GET_PROTOCOL 0x03 +#define UX_DEVICE_CLASS_HID_COMMAND_SET_REPORT 0x09 +#define UX_DEVICE_CLASS_HID_COMMAND_SET_IDLE 0x0A +#define UX_DEVICE_CLASS_HID_COMMAND_SET_PROTOCOL 0x0B + +/* Define HID Class Descriptor types. */ + +#define UX_DEVICE_CLASS_HID_DESCRIPTOR_HID 0x21 +#define UX_DEVICE_CLASS_HID_DESCRIPTOR_REPORT 0x22 +#define UX_DEVICE_CLASS_HID_DESCRIPTOR_PHYSICAL 0x23 + +/* Define HID Report Types. */ + +#define UX_DEVICE_CLASS_HID_REPORT_TYPE_INPUT 0x1 +#define UX_DEVICE_CLASS_HID_REPORT_TYPE_OUTPUT 0x2 +#define UX_DEVICE_CLASS_HID_REPORT_TYPE_FEATURE 0x3 + +/* Define HID event info structure. */ + +#ifndef UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH +#define UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH 32 +#endif + +/* Ensure the event buffer can fit inside the control endpoint's data buffer. */ +#if UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH +#error "Error: the event buffer cannot fit inside the control endpoint's data buffer. Reduce UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH such that it is less than or equal to UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH." +#endif + +/* Ensure the event buffer can fit inside the interrupt endpoint's data buffer. */ +#if UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH > UX_SLAVE_REQUEST_DATA_MAX_LENGTH +#error "Error: the event buffer cannot fit inside the interrupt endpoint's data buffer. Reduce UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH such that it is less than or equal to UX_SLAVE_REQUEST_DATA_MAX_LENGTH." +#endif + +#ifndef UX_DEVICE_CLASS_HID_MAX_EVENTS_QUEUE +#define UX_DEVICE_CLASS_HID_MAX_EVENTS_QUEUE 16 +#endif + +#define UX_DEVICE_CLASS_HID_NEW_EVENT 1 +#define UX_DEVICE_CLASS_HID_NEW_IDLE_RATE 2 +#define UX_DEVICE_CLASS_HID_EVENTS_MASK 3 + +typedef struct UX_SLAVE_CLASS_HID_EVENT_STRUCT +{ + ULONG ux_device_class_hid_event_report_id; + ULONG ux_device_class_hid_event_report_type; + UCHAR ux_device_class_hid_event_buffer[UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH]; + ULONG ux_device_class_hid_event_length; + +} UX_SLAVE_CLASS_HID_EVENT; + +/* Define HID structure. */ + +typedef struct UX_SLAVE_CLASS_HID_STRUCT +{ + + UX_SLAVE_INTERFACE *ux_slave_class_hid_interface; + UX_SLAVE_ENDPOINT *ux_device_class_hid_interrupt_endpoint; + UINT ux_device_class_hid_state; + UINT (*ux_device_class_hid_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, UX_SLAVE_CLASS_HID_EVENT *); + UINT (*ux_device_class_hid_get_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, UX_SLAVE_CLASS_HID_EVENT *); + VOID (*ux_slave_class_hid_instance_activate)(VOID *); + VOID (*ux_slave_class_hid_instance_deactivate)(VOID *); + UCHAR *ux_device_class_hid_report_address; + ULONG ux_device_class_hid_report_id; + ULONG ux_device_class_hid_report_length; + TX_EVENT_FLAGS_GROUP ux_device_class_hid_event_flags_group; + ULONG ux_device_class_hid_event_idle_rate; + ULONG ux_device_class_hid_event_wait_timeout; + UX_SLAVE_CLASS_HID_EVENT *ux_device_class_hid_event_array; + UX_SLAVE_CLASS_HID_EVENT *ux_device_class_hid_event_array_head; + UX_SLAVE_CLASS_HID_EVENT *ux_device_class_hid_event_array_tail; + UX_SLAVE_CLASS_HID_EVENT *ux_device_class_hid_event_array_end; + +} UX_SLAVE_CLASS_HID; + +/* Define HID initialization command structure. */ + +typedef struct UX_SLAVE_CLASS_HID_PARAMETER_STRUCT +{ + + VOID (*ux_slave_class_hid_instance_activate)(VOID *); + VOID (*ux_slave_class_hid_instance_deactivate)(VOID *); + UCHAR *ux_device_class_hid_parameter_report_address; + ULONG ux_device_class_hid_parameter_report_id; + ULONG ux_device_class_hid_parameter_report_length; + UINT (*ux_device_class_hid_parameter_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, UX_SLAVE_CLASS_HID_EVENT *); + UINT (*ux_device_class_hid_parameter_get_callback)(struct UX_SLAVE_CLASS_HID_STRUCT *hid, UX_SLAVE_CLASS_HID_EVENT *); + +} UX_SLAVE_CLASS_HID_PARAMETER; + + +/* Define HID Class function prototypes. */ +UINT _ux_device_class_hid_descriptor_send(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, + ULONG request_index, ULONG host_length); +UINT _ux_device_class_hid_activate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_hid_deactivate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_hid_control_request(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_hid_entry(UX_SLAVE_CLASS_COMMAND *command); +VOID _ux_device_class_hid_interrupt_thread(ULONG hid_class); +UINT _ux_device_class_hid_initialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_hid_uninitialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_hid_event_set(UX_SLAVE_CLASS_HID *hid, + UX_SLAVE_CLASS_HID_EVENT *hid_event); +UINT _ux_device_class_hid_event_get(UX_SLAVE_CLASS_HID *hid, + UX_SLAVE_CLASS_HID_EVENT *hid_event); +UINT _ux_device_class_hid_report_set(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, + ULONG request_index, ULONG host_length); +UINT _ux_device_class_hid_report_get(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, + ULONG request_index, ULONG host_length); + + +/* Define Device HID Class API prototypes. */ + +#define ux_device_class_hid_entry _ux_device_class_hid_entry +#define ux_device_class_hid_event_set _ux_device_class_hid_event_set +#define ux_device_class_hid_event_get _ux_device_class_hid_event_get +#define ux_device_class_hid_report_set _ux_device_class_hid_report_set +#define ux_device_class_hid_report_get _ux_device_class_hid_report_get + + +#endif diff --git a/common/usbx_device_classes/inc/ux_device_class_pima.h b/common/usbx_device_classes/inc/ux_device_class_pima.h new file mode 100644 index 0000000..5506927 --- /dev/null +++ b/common/usbx_device_classes/inc/ux_device_class_pima.h @@ -0,0 +1,996 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_pima.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX PIMA class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_PIMA_H +#define UX_DEVICE_CLASS_PIMA_H + +/* Define PIMA Class constants. */ + +#define UX_DEVICE_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT 300000 +#define UX_DEVICE_CLASS_PIMA_CLASS 0x06 +#define UX_DEVICE_CLASS_PIMA_SUBCLASS 0X01 +#define UX_DEVICE_CLASS_PIMA_PROTOCOL 0X01 +#define UX_DEVICE_CLASS_PIMA_MAGIC_NUMBER 0x50494D41 +#define UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH 256 +#define UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH 64 +#define UX_DEVICE_CLASS_PIMA_MAX_PAYLOAD 1024 +#define UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE 1024 +#define UX_DEVICE_CLASS_PIMA_DEVICE_INFO_BUFFER_SIZE 1024 +#define UX_DEVICE_CLASS_PIMA_STORAGE_INFO_BUFFER_SIZE 1024 +#define UX_DEVICE_CLASS_PIMA_ARRAY_BUFFER_SIZE 1024 +#define UX_DEVICE_CLASS_PIMA_MAX_EVENTS_QUEUE 16 +#define UX_DEVICE_CLASS_PIMA_MAX_STORAGE_IDS 1 +#define UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH 256 +#define UX_DEVICE_CLASS_PIMA_ARRAY_MAX_LENGTH 256 +#define UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH 64 +#define UX_DEVICE_CLASS_PIMA_DEVICE_PROPERTIES_ARRAY_MAX_ITEMS 32 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROPERTIES_ARRAY_MAX_ITEMS 128 +#define UX_DEVICE_CLASS_PIMA_DEVICE_PROP_VALUE_BUFFER_SIZE 1024 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_VALUE_BUFFER_SIZE 1024 +#define UX_DEVICE_CLASS_PIMA_PROP_VALUE_SIZE 256 +#define UX_DEVICE_CLASS_PIMA_MICROSOFT_VENDOR_COMMAND_CODE 0x54 + +/* Define PIMA versions. */ +#define UX_DEVICE_CLASS_PIMA_STANDARD_VERSION 100 +#define UX_DEVICE_CLASS_PIMA_VENDOR_EXTENSION_ID 6 +#define UX_DEVICE_CLASS_PIMA_EXTENSION_VERSION 100 +#define UX_DEVICE_CLASS_PIMA_STANDARD_MODE 0 + +/* Define PIMA data phases. */ + +#define UX_DEVICE_CLASS_PIMA_DATA_PHASE_NONE 0 +#define UX_DEVICE_CLASS_PIMA_DATA_PHASE_IN 1 +#define UX_DEVICE_CLASS_PIMA_DATA_PHASE_OUT 2 + +/* Define PIMA session states. */ + +#define UX_DEVICE_CLASS_PIMA_SESSION_STATE_CLOSED 0 +#define UX_DEVICE_CLASS_PIMA_SESSION_STATE_OPENED 1 + +/* Define PIMA object and thumb states. */ + +#define UX_DEVICE_CLASS_PIMA_OBJECT_STATE_CLOSED 0 +#define UX_DEVICE_CLASS_PIMA_OBJECT_STATE_OPENED 1 + +/* Define PIMA object and thumb transfer status. */ + +#define UX_DEVICE_CLASS_PIMA_OBJECT_TRANSFER_STATUS_INACTIVE 0 +#define UX_DEVICE_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ACTIVE 1 +#define UX_DEVICE_CLASS_PIMA_OBJECT_TRANSFER_STATUS_COMPLETED 2 +#define UX_DEVICE_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED 3 + +/* Define PIMA object and thumb transfer phase. */ + +#define UX_DEVICE_CLASS_PIMA_OBJECT_TRANSFER_PHASE_ACTIVE 0 +#define UX_DEVICE_CLASS_PIMA_OBJECT_TRANSFER_PHASE_COMPLETED 1 +#define UX_DEVICE_CLASS_PIMA_OBJECT_TRANSFER_PHASE_COMPLETED_ERROR 2 + + +/* Define PIMA Cancel Request equivalences. */ + +#define UX_DEVICE_CLASS_PIMA_REQUEST_CANCEL_COMMAND 0x64 +#define UX_DEVICE_CLASS_PIMA_REQUEST_CANCEL_DATA_LENGTH 0x06 +#define UX_DEVICE_CLASS_PIMA_REQUEST_CANCEL_CODE 0x04001 +#define UX_DEVICE_CLASS_PIMA_REQUEST_CANCEL_OFFSET_CODE 0x00 +#define UX_DEVICE_CLASS_PIMA_REQUEST_CANCEL_OFFSET_TRANSACTION_ID 0x02 + +/* Define PIMA Reset Request equivalences. */ + +#define UX_DEVICE_CLASS_PIMA_REQUEST_RESET_DEVICE 0x66 + +/* Define PIMA Status Request equivalences. */ + +#define UX_DEVICE_CLASS_PIMA_REQUEST_STATUS_COMMAND 0x67 +#define UX_DEVICE_CLASS_PIMA_REQUEST_STATUS_DATA_LENGTH 0x40 +#define UX_DEVICE_CLASS_PIMA_REQUEST_STATUS_OFFSET_LENGTH 0x00 +#define UX_DEVICE_CLASS_PIMA_REQUEST_STATUS_OFFSET_CODE 0x02 +#define UX_DEVICE_CLASS_PIMA_REQUEST_STATUS_COMMAND_COUNTER 16 +#define UX_DEVICE_CLASS_PIMA_REQUEST_STATUS_COMMAND_DELAY (1 * UX_PERIODIC_RATE) + +/* Define PIMA command container type. */ + +#define UX_DEVICE_CLASS_PIMA_CT_UNDEFINED 0x00 +#define UX_DEVICE_CLASS_PIMA_CT_COMMAND_BLOCK 0x01 +#define UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK 0x02 +#define UX_DEVICE_CLASS_PIMA_CT_RESPONSE_BLOCK 0x03 +#define UX_DEVICE_CLASS_PIMA_CT_EVENT_BLOCK 0x04 + +/* Define PIMA Extended Event Data Request payload Format. */ + +#define UX_DEVICE_CLASS_PIMA_EEDR_EVENT_CODE 0x00 +#define UX_DEVICE_CLASS_PIMA_EEDR_TRANSACTION_ID 0x02 +#define UX_DEVICE_CLASS_PIMA_EEDR_NUMBER_PARAMETERS 0x06 +#define UX_DEVICE_CLASS_PIMA_EEDR_SIZE_PARAMETER 0x08 + +/* Define PIMA Device Status Data Format. */ + +#define UX_DEVICE_CLASS_PIMA_DSD_LENGTH 0x00 +#define UX_DEVICE_CLASS_PIMA_DSD_CODE 0x02 +#define UX_DEVICE_CLASS_PIMA_DSD_PARAMETER 0x04 + +/* Define PIMA Command Header Format. */ + +#define UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_LENGTH 0x00 +#define UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_TYPE 0x04 +#define UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_CODE 0x06 +#define UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_TRANSACTION_ID 0x08 +#define UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_PARAMETER_1 0x0C +#define UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_PARAMETER_2 0x10 +#define UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_PARAMETER_3 0x14 +#define UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_PARAMETER_4 0x18 +#define UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_PARAMETER_5 0x1C + +#define UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_SIZE 0x0C +#define UX_DEVICE_CLASS_PIMA_CONTAINER_SIZE 0x40 +#define UX_DEVICE_CLASS_PIMA_ALL_HEADER_SIZE 0x20 + +/* Define PIMA Data Header Format. */ + +#define UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH 0x00 +#define UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE 0x04 +#define UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE 0x06 +#define UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID 0x08 +#define UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE 0x0C + + +/* Define PIMA Response Header Format. */ + +#define UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_LENGTH 0x00 +#define UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_TYPE 0x04 +#define UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_CODE 0x06 +#define UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_TRANSACTION_ID 0x08 +#define UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_PARAMETERS 0x0C +#define UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_SIZE 0x0C + +/* Define PIMA Asynchronous Event Interrupt Data Format. */ + +#define UX_DEVICE_CLASS_PIMA_AEI_DATA_LENGTH 0x00 +#define UX_DEVICE_CLASS_PIMA_AEI_TYPE 0x04 +#define UX_DEVICE_CLASS_PIMA_AEI_EVENT_CODE 0x06 +#define UX_DEVICE_CLASS_PIMA_AEI_TRANSACTION_ID 0x08 +#define UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_1 0x0C +#define UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_2 0x10 +#define UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_3 0x14 +#define UX_DEVICE_CLASS_PIMA_AEI_MAX_LENGTH 0x18 + +/* Define PIMA Operation Commands. */ + +#define UX_DEVICE_CLASS_PIMA_OC_UNDEFINED 0x1000 +#define UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_INFO 0x1001 +#define UX_DEVICE_CLASS_PIMA_OC_OPEN_SESSION 0x1002 +#define UX_DEVICE_CLASS_PIMA_OC_CLOSE_SESSION 0x1003 +#define UX_DEVICE_CLASS_PIMA_OC_GET_STORAGE_IDS 0x1004 +#define UX_DEVICE_CLASS_PIMA_OC_GET_STORAGE_INFO 0x1005 +#define UX_DEVICE_CLASS_PIMA_OC_GET_NUM_OBJECTS 0x1006 +#define UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_HANDLES 0x1007 +#define UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_INFO 0x1008 +#define UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT 0x1009 +#define UX_DEVICE_CLASS_PIMA_OC_GET_THUMB 0x100A +#define UX_DEVICE_CLASS_PIMA_OC_DELETE_OBJECT 0x100B +#define UX_DEVICE_CLASS_PIMA_OC_SEND_OBJECT_INFO 0x100C +#define UX_DEVICE_CLASS_PIMA_OC_SEND_OBJECT 0x100D +#define UX_DEVICE_CLASS_PIMA_OC_INITIATE_CAPTURE 0x100E +#define UX_DEVICE_CLASS_PIMA_OC_FORMAT_STORE 0x100F +#define UX_DEVICE_CLASS_PIMA_OC_RESET_DEVICE 0x1010 +#define UX_DEVICE_CLASS_PIMA_OC_SELF_TEST 0x1011 +#define UX_DEVICE_CLASS_PIMA_OC_SET_OBJECT_PROTECTION 0x1012 +#define UX_DEVICE_CLASS_PIMA_OC_POWER_DOWN 0x1013 +#define UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_PROP_DESC 0x1014 +#define UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_PROP_VALUE 0x1015 +#define UX_DEVICE_CLASS_PIMA_OC_SET_DEVICE_PROP_VALUE 0x1016 +#define UX_DEVICE_CLASS_PIMA_OC_RESET_DEVICE_PROP_VALUE 0x1017 +#define UX_DEVICE_CLASS_PIMA_OC_TERMINATE_OPEN_CAPTURE 0x1018 +#define UX_DEVICE_CLASS_PIMA_OC_MOVE_OBJECT 0x1019 +#define UX_DEVICE_CLASS_PIMA_OC_COPY_OBJECT 0x101A +#define UX_DEVICE_CLASS_PIMA_OC_GET_PARTIAL_OBJECT 0x101B +#define UX_DEVICE_CLASS_PIMA_OC_INITIATE_OPEN_CAPTURE 0x101C +#define UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROPS_SUPPORTED 0x9801 +#define UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROP_DESC 0x9802 +#define UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROP_VALUE 0x9803 +#define UX_DEVICE_CLASS_PIMA_OC_SET_OBJECT_PROP_VALUE 0x9804 +#define UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_REFERENCES 0x9810 +#define UX_DEVICE_CLASS_PIMA_OC_SET_OBJECT_REFERENCES 0x9811 + +/* Define PIMA Response Codes. */ + +#define UX_DEVICE_CLASS_PIMA_RC_UNDEFINED 0x2000 +#define UX_DEVICE_CLASS_PIMA_RC_OK 0x2001 +#define UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR 0x2002 +#define UX_DEVICE_CLASS_PIMA_RC_SESSION_NOT_OPEN 0x2003 +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_TRANSACTION_ID 0x2004 +#define UX_DEVICE_CLASS_PIMA_RC_OPERATION_NOT_SUPPORTED 0x2005 +#define UX_DEVICE_CLASS_PIMA_RC_PARAMETER_NOT_SUPPORTED 0x2006 +#define UX_DEVICE_CLASS_PIMA_RC_INCOMPLETE_TRANSFER 0x2007 +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_STORAGE_ID 0x2008 +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_HANDLE 0x2009 +#define UX_DEVICE_CLASS_PIMA_RC_DEVICE_PROP_NOT_SUPPORTED 0x200A +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_FORMAT_CODE 0x200B +#define UX_DEVICE_CLASS_PIMA_RC_STORE_FULL 0x200C +#define UX_DEVICE_CLASS_PIMA_RC_OBJECT_WRITE_PROTECTED 0x200D +#define UX_DEVICE_CLASS_PIMA_RC_STORE_READ_ONLY 0x200E +#define UX_DEVICE_CLASS_PIMA_RC_ACCESS_DENIED 0x200F +#define UX_DEVICE_CLASS_PIMA_RC_NO_THUMBNAIL_PRESENT 0x2010 +#define UX_DEVICE_CLASS_PIMA_RC_SELF_TEST_FAILED 0x2011 +#define UX_DEVICE_CLASS_PIMA_RC_PARTIAL_DELETION 0x2012 +#define UX_DEVICE_CLASS_PIMA_RC_STORE_NOT_AVAILABLE 0x2013 +#define UX_DEVICE_CLASS_PIMA_RC_FORMAT_UNSUPPORTED 0x2014 +#define UX_DEVICE_CLASS_PIMA_RC_NO_VALID_OBJECT_INFO 0x2015 +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_CODE_FORMAT 0x2016 +#define UX_DEVICE_CLASS_PIMA_RC_UNKNOWN_VENDOR_CODE 0x2017 +#define UX_DEVICE_CLASS_PIMA_RC_CAPTURE_ALREADY_TERMINATED 0x2018 +#define UX_DEVICE_CLASS_PIMA_RC_DEVICE_BUSY 0x2019 +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_PARENT_OBJECT 0x201A +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_DEVICE_PROP_FORMAT 0x201B +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_DEVICE_PROP_VALUE 0x201C +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER 0x201D +#define UX_DEVICE_CLASS_PIMA_RC_SESSION_ALREADY_OPENED 0x201E +#define UX_DEVICE_CLASS_PIMA_RC_TRANSACTION_CANCELED 0x201F +#define UX_DEVICE_CLASS_PIMA_RC_DESTINATION_UNSUPPORTED 0x2020 +#define UX_DEVICE_CLASS_PIMA_RC_OBJECT_ALREADY_OPENED 0x2021 +#define UX_DEVICE_CLASS_PIMA_RC_OBJECT_ALREADY_CLOSED 0x2022 +#define UX_DEVICE_CLASS_PIMA_RC_OBJECT_NOT_OPENED 0x2023 + +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_PROP_CODE 0xA801 +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_PROP_FORMAT 0xA802 +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_PROP_VALUE 0xA803 +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_REFERENCE 0xA804 +#define UX_DEVICE_CLASS_PIMA_RC_INVALID_DATASET 0xA806 +#define UX_DEVICE_CLASS_PIMA_RC_SPECIFICATION_BY_GROUP_UNSUPPORTED 0xA807 +#define UX_DEVICE_CLASS_PIMA_RC_SPECIFICATION_BY_DEPTH_UNSUPPORTED 0xA808 +#define UX_DEVICE_CLASS_PIMA_RC_OBJECT_TOO_LARGE 0xA809 +#define UX_DEVICE_CLASS_PIMA_RC_OBJECT_PROP_NOT_SUPPORTED 0xA80A + +/* Define PIMA Event Codes. */ + +#define UX_DEVICE_CLASS_PIMA_EC_UNDEFINED 0x4000 +#define UX_DEVICE_CLASS_PIMA_EC_CANCEL_TRANSACTION 0x4001 +#define UX_DEVICE_CLASS_PIMA_EC_OBJECT_ADDED 0x4002 +#define UX_DEVICE_CLASS_PIMA_EC_OBJECT_REMOVED 0x4003 +#define UX_DEVICE_CLASS_PIMA_EC_STORE_ADDED 0x4004 +#define UX_DEVICE_CLASS_PIMA_EC_STORE_REMOVED 0x4005 +#define UX_DEVICE_CLASS_PIMA_EC_DEVICE_PROP_CHANGED 0x4006 +#define UX_DEVICE_CLASS_PIMA_EC_OBJECT_INFO_CHANGED 0x4007 +#define UX_DEVICE_CLASS_PIMA_EC_DEVICE_INFO_CHANGED 0x4008 +#define UX_DEVICE_CLASS_PIMA_EC_REQUEST_OBJECT_TRANSFER 0x4009 +#define UX_DEVICE_CLASS_PIMA_EC_STORE_FULL 0x400A +#define UX_DEVICE_CLASS_PIMA_EC_DEVICE_RESET 0x400B +#define UX_DEVICE_CLASS_PIMA_EC_STORAGE_INFO_CHANGED 0x400C +#define UX_DEVICE_CLASS_PIMA_EC_CAPTURE_COMPLETE 0x400D +#define UX_DEVICE_CLASS_PIMA_EC_UNREPORTED_STATUS 0x400E + +/* Define PIMA Object Format Codes. */ + +#define UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED 0x3000 +#define UX_DEVICE_CLASS_PIMA_OFC_ASSOCIATION 0x3001 +#define UX_DEVICE_CLASS_PIMA_OFC_SCRIPT 0x3002 +#define UX_DEVICE_CLASS_PIMA_OFC_EXECUTABLE 0x3003 +#define UX_DEVICE_CLASS_PIMA_OFC_TEXT 0x3004 +#define UX_DEVICE_CLASS_PIMA_OFC_HTML 0x3005 +#define UX_DEVICE_CLASS_PIMA_OFC_DPOF 0x3006 +#define UX_DEVICE_CLASS_PIMA_OFC_AIFF 0x3007 +#define UX_DEVICE_CLASS_PIMA_OFC_WAV 0x3008 +#define UX_DEVICE_CLASS_PIMA_OFC_MP3 0x3009 +#define UX_DEVICE_CLASS_PIMA_OFC_AVI 0x300A +#define UX_DEVICE_CLASS_PIMA_OFC_MPEG 0x300B +#define UX_DEVICE_CLASS_PIMA_OFC_ASF 0x300C +#define UX_DEVICE_CLASS_PIMA_OFC_DEFINED 0x3800 +#define UX_DEVICE_CLASS_PIMA_OFC_EXIF_JPEG 0x3801 +#define UX_DEVICE_CLASS_PIMA_OFC_TIFF_EP 0x3802 +#define UX_DEVICE_CLASS_PIMA_OFC_FLASHPIX 0x3803 +#define UX_DEVICE_CLASS_PIMA_OFC_BMP 0x3804 +#define UX_DEVICE_CLASS_PIMA_OFC_CIFF 0x3805 +#define UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_2 0x3806 +#define UX_DEVICE_CLASS_PIMA_OFC_GIF 0x3807 +#define UX_DEVICE_CLASS_PIMA_OFC_JFIF 0x3808 +#define UX_DEVICE_CLASS_PIMA_OFC_CD 0x3809 +#define UX_DEVICE_CLASS_PIMA_OFC_PICT 0x380A +#define UX_DEVICE_CLASS_PIMA_OFC_PNG 0x380B +#define UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_3 0x380C +#define UX_DEVICE_CLASS_PIMA_OFC_TIFF 0x380D +#define UX_DEVICE_CLASS_PIMA_OFC_TIFF_IT 0x380E +#define UX_DEVICE_CLASS_PIMA_OFC_JP2 0x380F +#define UX_DEVICE_CLASS_PIMA_OFC_JPX 0x3810 +#define UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_FIRMWARE 0xB802 +#define UX_DEVICE_CLASS_PIMA_OFC_WINDOWS_IMAGE_FORMAT 0xB881 +#define UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_AUDIO 0xB900 +#define UX_DEVICE_CLASS_PIMA_OFC_WMA 0xB901 +#define UX_DEVICE_CLASS_PIMA_OFC_OGG 0xB902 +#define UX_DEVICE_CLASS_PIMA_OFC_AAC 0xB903 +#define UX_DEVICE_CLASS_PIMA_OFC_AUDIBLE 0xB904 +#define UX_DEVICE_CLASS_PIMA_OFC_FLAC 0xB906 +#define UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_VIDEO 0xB980 +#define UX_DEVICE_CLASS_PIMA_OFC_WMV 0xB981 +#define UX_DEVICE_CLASS_PIMA_OFC_MP4_CONTAINER 0xB982 +#define UX_DEVICE_CLASS_PIMA_OFC_MP2 0xB983 +#define UX_DEVICE_CLASS_PIMA_OFC_3GP_CONTAINER 0xB984 +#define UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_COLLECTION 0xBA00 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_MULTIMEDIA_ALBUM 0xBA01 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_IMAGE_ALBUM 0xBA02 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_AUDIO_ALBUM 0xBA03 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_VIDEO_ALBUM 0xBA04 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_AUDIO_AND_VIDEO_PLAYLIST 0xBA05 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_CONTACT_GROUP 0xBA06 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_MESSAGE_FOLDER 0xBA07 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_CHAPTERED_PRODUCTION 0xBA08 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_AUDIO_PLAYLIST 0xBA09 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_VIDEO_PLAYLIST 0xBA0A +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_MEDIACAST 0xBA0B +#define UX_DEVICE_CLASS_PIMA_OFC_WPL_PLAYLIST 0xBA10 +#define UX_DEVICE_CLASS_PIMA_OFC_M3U_PLAYLIST 0xBA11 +#define UX_DEVICE_CLASS_PIMA_OFC_MPL_PLAYLIST 0xBA12 +#define UX_DEVICE_CLASS_PIMA_OFC_ASX_PLAYLIST 0xBA13 +#define UX_DEVICE_CLASS_PIMA_OFC_PLS_PLAYLIST 0xBA14 +#define UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_DOCUMENT 0xBA80 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_DOCUMENT 0xBA81 +#define UX_DEVICE_CLASS_PIMA_OFC_XML_DOCUMENT 0xBA82 +#define UX_DEVICE_CLASS_PIMA_OFC_MICROSOFT_WORD_DOCUMENT 0xBA83 +#define UX_DEVICE_CLASS_PIMA_OFC_MHT_COMPILED_HTML_DOCUMENT 0xBA84 +#define UX_DEVICE_CLASS_PIMA_OFC_MICROSOFT_EXCEL_SPREADSHEET 0xBA85 +#define UX_DEVICE_CLASS_PIMA_OFC_MICROSOFT_POWERPOINT_PRESENTATION 0xBA86 +#define UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_MESSAGE 0xBB00 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_MESSAGE 0xBB01 +#define UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_CONTACT 0xBB80 +#define UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_CONTACT 0xBB81 +#define UX_DEVICE_CLASS_PIMA_OFC_VCARD2 0xBB82 + +/* Define PIMA Device Format Codes. */ + +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_UNDEFINED 0x5000 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_BATTERY_LEVEL 0x5001 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_FUNCTIONAL_MODE 0x5002 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_IMAGE_SIZE 0x5003 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_COMPRESSION_SETTING 0x5004 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_WHITE_BALANCE 0x5005 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_RGB_GAIN 0x5006 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_F_NUMBER 0x5007 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_FOCAL_LENGTH 0x5008 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_FOCUS_DISTANCE 0x5009 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_FOCUS_MODE 0x500A +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_EXPOSURE_METERING_MODE 0x500B +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_FLASH_MODE 0x500C +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_EXPOSURE_TIME 0x500D +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_EXPOSURE_PROGRAM_MODE 0x500E +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_EXPOSURE_INDEX 0x500F +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_EXPOSURE_BIAS_COMPENSATION 0x5010 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_DATE_TIME 0x5011 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_CAPTURE_DELAY 0x5012 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_STILL_CAPTURE_MODE 0x5013 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_CONTRAST 0x5014 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_SHARPNESS 0x5015 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_DIGITAL_ZOOM 0x5016 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_EFFECT_MODE 0x5017 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_BURST_NUMBER 0x5018 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_BURST_INTERVAL 0x5019 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_TIME_LAPSE_NUMBER 0x501A +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_TIME_LAPSE_INTERVAL 0x501B +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_FOCUS_METERING_MODE 0x501C +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_UPLOAD_URL 0x501D +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_ARTIST 0x501E +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_COPYRIGHT_INFO 0x501F +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_SYNCHRONIZATION_PARTNER 0xD401 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_DEVICE_FRIENDLY_NAME 0xD402 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_VOLUME 0xD403 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_SUPPORTED_FORMATS_ORDERED 0xD404 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_DEVICE_ICON 0xD405 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_PLAYBACK_RATE 0xD410 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_PLAYBACK_OBJECT 0xD411 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_PLAYBACK_CONTAINER 0xD412 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_SESSION_INITIATOR_VERSION_INFO 0xD406 +#define UX_DEVICE_CLASS_PIMA_DEV_PROP_PERCEIVED_DEVICE_TYPE 0xD407 + +/* Define PIMA Object Format Codes. */ + +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_STORAGEID 0xDC01 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_OBJECT_FORMAT 0xDC02 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PROTECTION_STATUS 0xDC03 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_OBJECT_SIZE 0xDC04 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ASSOCIATION_TYPE 0xDC05 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ASSOCIATION_DESC 0xDC06 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_OBJECT_FILE_NAME 0xDC07 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_DATE_CREATED 0xDC08 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_DATE_MODIFIED 0xDC09 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_KEYWORDS 0xDC0A +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PARENT_OBJECT 0xDC0B +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ALLOWED_FOLDER_CONTENTS 0xDC0C +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_HIDDEN 0xDC0D +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_SYSTEM_OBJECT 0xDC0E +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PERSISTENT_UNIQUE_OBJECT_IDENTIFIER 0xDC41 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_SYNCID 0xDC42 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PROPERTY_BAG 0xDC43 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_NAME 0xDC44 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_CREATED_BY 0xDC45 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ARTIST 0xDC46 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_DATE_AUTHORED 0xDC47 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_DESCRIPTION 0xDC48 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_URL_REFERENCE 0xDC49 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_LANGUAGE_LOCALE 0xDC4A +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_COPYRIGHT_INFORMATION 0xDC4B +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_SOURCE 0xDC4C +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ORIGIN_LOCATION 0xDC4D +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_DATE_ADDED 0xDC4E +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_NON_CONSUMABLE 0xDC4F +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_CORRUPT_UNPLAYABLE 0xDC50 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PRODUCER_SERIA_LNUMBER 0xDC51 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_REPRESENTATIVE_SAMPLE_FORMAT 0xDC81 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_REPRESENTATIVE_SAMPLE_SIZE 0xDC82 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_REPRESENTATIVE_SAMPLE_HEIGHT 0xDC83 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_REPRESENTATIVE_SAMPLE_WIDTH 0xDC84 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_REPRESENTATIVE_SAMPLE_DURATION 0xDC85 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_REPRESENTATIVE_SAMPLE_DATA 0xDC86 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_WIDTH 0xDC87 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_HEIGHT 0xDC88 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_DURATION 0xDC89 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_RATING 0xDC8A +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_TRACK 0xDC8B +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_GENRE 0xDC8C +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_CREDITS 0xDC8D +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_LYRICS 0xDC8E +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_SUBSCRIPTION_CONTENT_ID 0xDC8F +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PRODUCED_BY 0xDC90 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_USE_COUNT 0xDC91 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_SKIP_COUNT 0xDC92 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_LAST_ACCESSED 0xDC93 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PARENTAL_RATING 0xDC94 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_META_GENRE 0xDC95 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_COMPOSER 0xDC96 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_EFFECTIVE_RATING 0xDC97 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_SUBTITLE 0xDC98 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ORIGINAL_RELEASE_DATE 0xDC99 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ALBUM_NAME 0xDC9A +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ALBUM_ARTIST 0xDC9B +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_MOOD 0xDC9C +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_DRM_STATUS 0xDC9D +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_SUB_DESCRIPTION 0xDC9E +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_IS_CROPPED 0xDCD1 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_IS_COLOUR_CORRECTED 0xDCD2 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_IMAGE_BIT_DEPTH 0xDCD3 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_FNUMBER 0xDCD4 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_EXPOSURE_TIME 0xDCD5 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_EXPOSURE_INDEX 0xDCD6 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_TOTAL_BITRATE 0xDE91 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_BITRATE_TYPE 0xDE92 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_SAMPLE_RATE 0xDE93 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_NUMBER_OF_CHANNELS 0xDE94 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_AUDIO_BITDEPTH 0xDE95 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_SCAN_TYPE 0xDE97 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_AUDIO_WAVE_CODEC 0xDE99 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_AUDIO_BITRATE 0xDE9A +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_VIDEO_FOURCC_CODEC 0xDE9B +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_VIDEO_BITRATE 0xDE9C +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_FRAMES_PER_THOUSAND_SECONDS 0xDE9D +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_KEYFRAME_DISTANCE 0xDE9E +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_BUFFER_SIZE 0xDE9F +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ENCODING_QUALITY 0xDEA0 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ENCODING_PROFILE 0xDEA1 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_DISPLAY_NAME 0xDCE0 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_BODY_TEXT 0xDCE1 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_SUBJECT 0xDCE2 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PRIORITY 0xDCE3 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_GIVEN_NAME 0xDD00 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_MIDDLE_NAMES 0xDD01 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_FAMILY_NAME 0xDD02 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PREFIX 0xDD03 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_SUFFIX 0xDD04 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PHONETIC_GIVEN_NAME 0xDD05 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PHONETIC_FAMILY_NAME 0xDD06 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_EMAIL_PRIMARY 0xDD07 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_EMAIL_PERSONAL_1 0xDD08 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_EMAIL_PERSONAL_2 0xDD09 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_EMAIL_BUSINESS_1 0xDD0A +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_EMAIL_BUSINESS_2 0xDD0B +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_EMAIL_OTHERS 0xDD0C +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PHONE_NUMBER_PRIMARY 0xDD0D +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PHONE_NUMBER_PERSONAL 0xDD0E +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PHONE_NUMBER_PERSONAL_2 0xDD0F +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PHONE_NUMBER_BUSINESS 0xDD10 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PHONE_NUMBER_BUSINESS_2 0xDD11 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PHONE_NUMBER_MOBILE 0xDD12 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PHONE_NUMBER_MOBILE_2 0xDD13 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_FAX_NUMBER_PRIMARY 0xDD14 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_FAX_NUMBER_PERSONAL 0xDD15 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_FAX_NUMBER_BUSINESS 0xDD16 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PAGER_NUMBER 0xDD17 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PHONE_NUMBER_OTHERS 0xDD18 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PRIMARY_WEB_ADDRESS 0xDD19 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PERSONAL_WEB_ADDRESS 0xDD1A +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_BUSINESS_WEB_ADDRESS 0xDD1B +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_INSTANT_MESSENGER_ADDRESS 0xDD1C +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_INSTANT_MESSENGER_ADDRESS_2 0xDD1D +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_INSTANT_MESSENGER_ADDRESS_3 0xDD1E +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_PERSONAL_FULL 0xDD1F +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_PERSONAL_LINE_1 0xDD20 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_PERSONAL_LINE_2 0xDD21 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_PERSONAL_CITY 0xDD22 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_PERSONAL_REGION 0xDD23 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_PERSONAL_POSTAL_CODE 0xDD24 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_PERSONAL_COUNTRY 0xDD25 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_BUSINESS_FULL 0xDD26 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_BUSINESS_LINE_1 0xDD27 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_BUSINESS_LINE_2 0xDD28 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_BUSINESS_CITY 0xDD29 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_BUSINESS_REGION 0xDD2A +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_BUSINESS_POSTAL_CODE 0xDD2B +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_BUSINESS_COUNTRY 0xDD2C +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_OTHER_FULL 0xDD2D +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_OTHER_LINE_1 0xDD2E +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_OTHER_LINE_2 0xDD2F +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_OTHER_CITY 0xDD30 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_OTHER_REGION 0xDD31 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_OTHER_POSTAL_CODE 0xDD32 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_POSTAL_ADDRESS_OTHER_COUNTRY 0xDD33 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ORGANIZATION_NAME 0xDD34 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_PHONETIC_ORGANIZATION_NAME 0xDD35 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ROLE 0xDD36 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_BIRTHDATE 0xDD37 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_MESSAGE_TO 0xDD40 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_MESSAGE_CC 0xDD41 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_MESSAGE_BCC 0xDD42 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_MESSAGE_READ 0xDD43 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_MESSAGE_RECEIVED_TIME 0xDD44 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_MESSAGE_SENDER 0xDD45 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ACTIVITY_BEGIN_TIME 0xDD50 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ACTIVITY_END_TIME 0xDD51 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ACTIVITY_LOCATION 0xDD52 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ACTIVITY_REQUIRED_ATTENDEES 0xDD54 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ACTIVITY_OPTIONAL_ATTENDEES 0xDD55 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ACTIVITY_RESOURCES 0xDD56 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_ACTIVITY_ACCEPTED 0xDD57 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_OWNER 0xDD5D +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_EDITOR 0xDD5E +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_WEBMASTER 0xDD5F +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_URL_SOURCE 0xDD60 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_URL_DESTINATION 0xDD61 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_TIME_BOOKMARK 0xDD62 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_OBJECT_BOOKMARK 0xDD63 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_BYTE_BOOKMARK 0xDD64 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_LAST_BUILD_DATE 0xDD70 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_TIME_TO_LIVE 0xDD71 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROP_MEDIA_GUID 0xDD72 + +/* Define PIMA Object Protection Status Values. */ + +#define UX_DEVICE_CLASS_PIMA_OPS_NO_PROTECTION 0x0000 +#define UX_DEVICE_CLASS_PIMA_OPS_READ_ONLY 0x0001 + +/* Define PIMA Storage Types Codes. */ + +#define UX_DEVICE_CLASS_PIMA_STC_UNDEFINED 0x0000 +#define UX_DEVICE_CLASS_PIMA_STC_FIXED_ROM 0x0001 +#define UX_DEVICE_CLASS_PIMA_STC_REMOVABLE_ROM 0x0002 +#define UX_DEVICE_CLASS_PIMA_STC_FIXED_RAM 0x0003 +#define UX_DEVICE_CLASS_PIMA_STC_REMOVABLE_RAM 0x0004 + +/* Define PIMA File System Types Codes. */ + +#define UX_DEVICE_CLASS_PIMA_FSTC_UNDEFINED 0x0000 +#define UX_DEVICE_CLASS_PIMA_FSTC_GENERIC_FLAT 0x0001 +#define UX_DEVICE_CLASS_PIMA_FSTC_GENERIC_HIERARCHICAL 0x0002 +#define UX_DEVICE_CLASS_PIMA_FSTC_DCF 0x0003 + +/* Define PIMA File System Access Types Codes. */ + +#define UX_DEVICE_CLASS_PIMA_AC_READ_WRITE 0x0000 +#define UX_DEVICE_CLASS_PIMA_AC_RO_WITHOUT_OBJECT_DELETION 0x0001 +#define UX_DEVICE_CLASS_PIMA_AC_RO_WITH_OBJECT_DELETION 0x0002 + +/* Define PIMA types. */ +#define UX_DEVICE_CLASS_PIMA_TYPES_INT8 0x0001 +#define UX_DEVICE_CLASS_PIMA_TYPES_UINT8 0x0002 +#define UX_DEVICE_CLASS_PIMA_TYPES_INT16 0x0003 +#define UX_DEVICE_CLASS_PIMA_TYPES_UINT16 0x0004 +#define UX_DEVICE_CLASS_PIMA_TYPES_INT32 0x0005 +#define UX_DEVICE_CLASS_PIMA_TYPES_UINT32 0x0006 +#define UX_DEVICE_CLASS_PIMA_TYPES_INT64 0x0007 +#define UX_DEVICE_CLASS_PIMA_TYPES_UINT64 0x0008 +#define UX_DEVICE_CLASS_PIMA_TYPES_INT128 0x0009 +#define UX_DEVICE_CLASS_PIMA_TYPES_UINT128 0x000A +#define UX_DEVICE_CLASS_PIMA_TYPES_AINT8 0x4001 +#define UX_DEVICE_CLASS_PIMA_TYPES_AUINT8 0x4002 +#define UX_DEVICE_CLASS_PIMA_TYPES_AINT16 0x4003 +#define UX_DEVICE_CLASS_PIMA_TYPES_AUINT16 0x4004 +#define UX_DEVICE_CLASS_PIMA_TYPES_AINT32 0x4005 +#define UX_DEVICE_CLASS_PIMA_TYPES_AUINT32 0x4006 +#define UX_DEVICE_CLASS_PIMA_TYPES_AINT64 0x4007 +#define UX_DEVICE_CLASS_PIMA_TYPES_AUINT64 0x4008 +#define UX_DEVICE_CLASS_PIMA_TYPES_AINT128 0x4009 +#define UX_DEVICE_CLASS_PIMA_TYPES_AUINT128 0x400A +#define UX_DEVICE_CLASS_PIMA_TYPES_STR 0xFFFF + +/* Define PIMA Device Info fields. */ + +#define UX_DEVICE_CLASS_PIMA_DEVICE_INFO_STANDARD_VERSION (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 0x0000) +#define UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_ID (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 0x0002) +#define UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_VERSION (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 0x0006) +#define UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_DESC (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 0x0008) + +/* Define PIMA MTP OBJECT PROPERTY DATASET. */ +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROPERTY_DATASET_CODE 0x0000 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROPERTY_DATASET_DATATYPE 0x0002 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROPERTY_DATASET_GETSET 0x0004 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROPERTY_DATASET_VALUE 0x0005 + +/* Define PIMA Dataset equivalences. */ +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROPERTY_DATASET_VALUE_GET 0x00 +#define UX_DEVICE_CLASS_PIMA_OBJECT_PROPERTY_DATASET_VALUE_GETSET 0x01 + +/* Define PIMA event info structure. */ + +typedef struct UX_SLAVE_CLASS_PIMA_EVENT_STRUCT +{ + ULONG ux_device_class_pima_event_code; + ULONG ux_device_class_pima_event_session_id; + ULONG ux_device_class_pima_event_transaction_id; + ULONG ux_device_class_pima_event_parameter_1; + ULONG ux_device_class_pima_event_parameter_2; + ULONG ux_device_class_pima_event_parameter_3; + +} UX_SLAVE_CLASS_PIMA_EVENT; + +/* Define PIMA object info structure. */ + +typedef struct UX_SLAVE_CLASS_PIMA_OBJECT_STRUCT +{ + + ULONG ux_device_class_pima_object_storage_id; + ULONG ux_device_class_pima_object_format; + ULONG ux_device_class_pima_object_protection_status; + ULONG ux_device_class_pima_object_compressed_size; + ULONG ux_device_class_pima_object_thumb_format; + ULONG ux_device_class_pima_object_thumb_compressed_size; + ULONG ux_device_class_pima_object_thumb_pix_width; + ULONG ux_device_class_pima_object_thumb_pix_height; + ULONG ux_device_class_pima_object_image_pix_width; + ULONG ux_device_class_pima_object_image_pix_height; + ULONG ux_device_class_pima_object_image_bit_depth; + ULONG ux_device_class_pima_object_parent_object; + ULONG ux_device_class_pima_object_association_type; + ULONG ux_device_class_pima_object_association_desc; + ULONG ux_device_class_pima_object_sequence_number; + UCHAR ux_device_class_pima_object_filename[UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH]; + UCHAR ux_device_class_pima_object_capture_date[UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH]; + UCHAR ux_device_class_pima_object_modification_date[UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH]; + UCHAR ux_device_class_pima_object_keywords[UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH]; + ULONG ux_device_class_pima_object_state; + ULONG ux_device_class_pima_object_offset; + ULONG ux_device_class_pima_object_transfer_status; + ULONG ux_device_class_pima_object_handle_id; + ULONG ux_device_class_pima_object_length; + UCHAR *ux_device_class_pima_object_buffer; + +} UX_SLAVE_CLASS_PIMA_OBJECT; + +#define UX_SLAVE_CLASS_PIMA_OBJECT_DATA_LENGTH ((15 * sizeof(ULONG)) + \ + UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH + \ + UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH + \ + UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH + \ + UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH) + +/* Define PIMA session info structure. Not used in the device. Here for structure compatibility. */ + +typedef struct UX_SLAVE_CLASS_PIMA_SESSION_STRUCT +{ + + ULONG ux_device_class_pima_session_id; + +} UX_SLAVE_CLASS_PIMA_SESSION; + +/* Define PIMA device info structure. */ + +typedef struct UX_SLAVE_CLASS_PIMA_DEVICE_STRUCT +{ + + ULONG ux_device_class_pima_device_standard_version; + ULONG ux_device_class_pima_device_vendor_extension_id; + ULONG ux_device_class_pima_device_vendor_extension_version; + UCHAR ux_device_class_pima_device_vendor_extension_desc[UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH]; + ULONG ux_device_class_pima_device_functional_mode; + UCHAR ux_device_class_pima_device_operations_supported[UX_DEVICE_CLASS_PIMA_ARRAY_MAX_LENGTH]; + UCHAR ux_device_class_pima_device_events_supported[UX_DEVICE_CLASS_PIMA_ARRAY_MAX_LENGTH]; + UCHAR ux_device_class_pima_device_properties_supported[UX_DEVICE_CLASS_PIMA_ARRAY_MAX_LENGTH]; + UCHAR ux_device_class_pima_device_capture_formats[UX_DEVICE_CLASS_PIMA_ARRAY_MAX_LENGTH]; + UCHAR ux_device_class_pima_device_image_formats[UX_DEVICE_CLASS_PIMA_ARRAY_MAX_LENGTH]; + UCHAR ux_device_class_pima_device_manufacturer[UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH]; + UCHAR ux_device_class_pima_device_model[UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH]; + UCHAR ux_device_class_pima_device_version[UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH]; + UCHAR ux_device_class_pima_device_serial_number[UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH]; + +} UX_SLAVE_CLASS_PIMA_DEVICE; + +/* Define PIMA storage info structure. */ + +typedef struct UX_SLAVE_CLASS_PIMA_STORAGE_STRUCT +{ + + ULONG ux_device_class_pima_storage_type; + ULONG ux_device_class_pima_storage_file_system_type; + ULONG ux_device_class_pima_storage_access_capability; + ULONG ux_device_class_pima_storage_max_capacity_low; + ULONG ux_device_class_pima_storage_max_capacity_high; + ULONG ux_device_class_pima_storage_free_space_bytes_low; + ULONG ux_device_class_pima_storage_free_space_bytes_high; + ULONG ux_device_class_pima_storage_free_space_images; + UCHAR ux_device_class_pima_storage_description[UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH]; + UCHAR ux__class_pima_storage_volume_label[UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH]; + +} UX_SLAVE_CLASS_PIMA_STORAGE; + +/* Define PIMA structure. */ + +typedef struct UX_SLAVE_CLASS_PIMA_STRUCT +{ + + UX_SLAVE_INTERFACE *ux_slave_class_pima_interface; + UX_SLAVE_ENDPOINT *ux_device_class_pima_bulk_in_endpoint; + UX_SLAVE_ENDPOINT *ux_device_class_pima_bulk_out_endpoint; + UX_SLAVE_ENDPOINT *ux_device_class_pima_interrupt_endpoint; + UINT ux_device_class_pima_state; + ULONG ux_device_class_pima_session_id; + ULONG ux_device_class_pima_current_object_handle; + ULONG ux_device_class_pima_transaction_id; + UCHAR *ux_device_class_pima_manufacturer; + UCHAR *ux_device_class_pima_model; + UCHAR *ux_device_class_pima_device_version; + UCHAR *ux_device_class_pima_serial_number; + ULONG ux_device_class_pima_storage_id; + ULONG ux_device_class_pima_storage_type; + ULONG ux_device_class_pima_storage_file_system_type; + ULONG ux_device_class_pima_storage_access_capability; + ULONG ux_device_class_pima_storage_max_capacity_low; + ULONG ux_device_class_pima_storage_max_capacity_high; + ULONG ux_device_class_pima_storage_free_space_low; + ULONG ux_device_class_pima_storage_free_space_high; + ULONG ux_device_class_pima_storage_free_space_image; + UCHAR *ux_device_class_pima_storage_description; + UCHAR *ux_device_class_pima_storage_volume_label; + TX_SEMAPHORE ux_device_class_pima_semaphore; + TX_THREAD ux_device_class_pima_interrupt_thread; + UCHAR *ux_device_class_pima_interrupt_thread_stack; + TX_SEMAPHORE ux_device_class_pima_interrupt_thread_semaphore; + UX_SLAVE_CLASS_PIMA_EVENT + *ux_device_class_pima_event_array; + UX_SLAVE_CLASS_PIMA_EVENT + *ux_device_class_pima_event_array_head; + UX_SLAVE_CLASS_PIMA_EVENT + *ux_device_class_pima_event_array_tail; + UX_SLAVE_CLASS_PIMA_EVENT + *ux_device_class_pima_event_array_end; + USHORT *ux_device_class_pima_device_properties_list; + USHORT *ux_device_class_pima_supported_capture_formats_list; + USHORT *ux_device_class_pima_supported_image_formats_list; + USHORT *ux_device_class_pima_object_properties_list; + UINT (*ux_device_class_pima_device_reset)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima); + + UINT (*ux_device_class_pima_device_prop_desc_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG device_property, UCHAR **device_prop_dataset, ULONG *device_prop_dataset_length); + UINT (*ux_device_class_pima_device_prop_value_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG device_property, UCHAR **device_prop_value, ULONG *device_prop_value_length); + UINT (*ux_device_class_pima_device_prop_value_set)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG device_property, UCHAR *device_prop_value, ULONG device_prop_value_length); + + UINT (*ux_device_class_pima_storage_format)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG storage_id); + UINT (*ux_device_class_pima_storage_info_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG storage_id); + UINT (*ux_device_class_pima_object_number_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_format_code, ULONG object_association, ULONG *object_number); + UINT (*ux_device_class_pima_object_handles_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handles_format_code, + ULONG object_handles_association, + ULONG *object_handles_array, + ULONG object_handles_max_number); + UINT (*ux_device_class_pima_object_info_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, UX_SLAVE_CLASS_PIMA_OBJECT **object); + UINT (*ux_device_class_pima_object_data_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, UCHAR *object_buffer, ULONG object_offset, + ULONG object_length_requested, ULONG *object_actual_length); + UINT (*ux_device_class_pima_object_info_send)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, UX_SLAVE_CLASS_PIMA_OBJECT *object, ULONG storage_id, ULONG parent_object_handle, ULONG *object_handle); + UINT (*ux_device_class_pima_object_data_send)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, ULONG phase, UCHAR *object_buffer, ULONG object_offset, + ULONG object_length); + UINT (*ux_device_class_pima_object_delete)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle); + UINT (*ux_device_class_pima_object_prop_desc_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_property, ULONG object_format_code, UCHAR **object_prop_value_dataset, ULONG *object_prop_value_dataset_length); + UINT (*ux_device_class_pima_object_prop_value_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, ULONG object_property, UCHAR **object_prop_value, ULONG *object_prop_value_length); + UINT (*ux_device_class_pima_object_prop_value_set)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, ULONG object_property, UCHAR *object_prop_value, ULONG object_prop_value_length); + UINT (*ux_device_class_pima_object_references_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, UCHAR **object_handle_array, ULONG *object_handle_array_length); + UINT (*ux_device_class_pima_object_references_set)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, UCHAR *object_handle_array, ULONG object_handle_array_length); + VOID *ux_device_class_pima_application; + VOID (*ux_device_class_pima_instance_activate)(VOID *); + VOID (*ux_device_class_pima_instance_deactivate)(VOID *); + + +} UX_SLAVE_CLASS_PIMA; + +/* Define PIMA initialization command structure. */ + +typedef struct UX_SLAVE_CLASS_PIMA_PARAMETER_STRUCT +{ + + VOID (*ux_device_class_pima_instance_activate)(VOID *); + VOID (*ux_device_class_pima_instance_deactivate)(VOID *); + UCHAR *ux_device_class_pima_parameter_manufacturer; + UCHAR *ux_device_class_pima_parameter_model; + UCHAR *ux_device_class_pima_parameter_device_version; + UCHAR *ux_device_class_pima_parameter_serial_number; + ULONG ux_device_class_pima_parameter_storage_id; + ULONG ux_device_class_pima_parameter_storage_type; + ULONG ux_device_class_pima_parameter_storage_file_system_type; + ULONG ux_device_class_pima_parameter_storage_access_capability; + ULONG ux_device_class_pima_parameter_storage_max_capacity_low; + ULONG ux_device_class_pima_parameter_storage_max_capacity_high; + ULONG ux_device_class_pima_parameter_storage_free_space_low; + ULONG ux_device_class_pima_parameter_storage_free_space_high; + ULONG ux_device_class_pima_parameter_storage_free_space_image; + UCHAR *ux_device_class_pima_parameter_storage_description; + UCHAR *ux_device_class_pima_parameter_storage_volume_label; + USHORT *ux_device_class_pima_parameter_device_properties_list; + USHORT *ux_device_class_pima_parameter_supported_capture_formats_list; + USHORT *ux_device_class_pima_parameter_supported_image_formats_list; + USHORT *ux_device_class_pima_parameter_object_properties_list; + UINT (*ux_device_class_pima_parameter_device_reset)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima); + UINT (*ux_device_class_pima_parameter_device_prop_desc_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG device_property, UCHAR **device_prop_dataset, ULONG *device_prop_dataset_length); + UINT (*ux_device_class_pima_parameter_device_prop_value_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG device_property, UCHAR **device_prop_value, ULONG *device_prop_value_length); + UINT (*ux_device_class_pima_parameter_device_prop_value_set)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG device_property, UCHAR *device_prop_value, ULONG device_prop_value_length); + UINT (*ux_device_class_pima_parameter_storage_format)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG storage_id); + UINT (*ux_device_class_pima_parameter_storage_info_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG storage_id); + UINT (*ux_device_class_pima_parameter_object_number_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_format_code, ULONG object_association, ULONG *object_number); + UINT (*ux_device_class_pima_parameter_object_handles_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handles_format_code, + ULONG object_handles_association, + ULONG *object_handles_array, + ULONG object_handles_max_number); + UINT (*ux_device_class_pima_parameter_object_info_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, UX_SLAVE_CLASS_PIMA_OBJECT **object); + UINT (*ux_device_class_pima_parameter_object_data_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, UCHAR *object_buffer, ULONG object_offset, + ULONG object_length_requested, ULONG *object_actual_length); + + UINT (*ux_device_class_pima_parameter_object_info_send)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, UX_SLAVE_CLASS_PIMA_OBJECT *object, ULONG storage_id, ULONG parent_object_handle, ULONG *object_handle); + UINT (*ux_device_class_pima_parameter_object_data_send)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, ULONG phase ,UCHAR *object_buffer, ULONG object_offset, + ULONG object_length); + UINT (*ux_device_class_pima_parameter_object_delete)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle); + UINT (*ux_device_class_pima_parameter_object_prop_desc_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, ULONG object_property, UCHAR **object_prop_dataset, ULONG *object_prop_dataset_length); + UINT (*ux_device_class_pima_parameter_object_prop_value_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, ULONG object_property, UCHAR **object_prop_value, ULONG *object_prop_value_length); + UINT (*ux_device_class_pima_parameter_object_prop_value_set)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, ULONG object_property, UCHAR *object_prop_value, ULONG object_prop_value_length); + UINT (*ux_device_class_pima_parameter_object_references_get)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, UCHAR **object_handle_array, ULONG *object_handle_array_length); + UINT (*ux_device_class_pima_parameter_object_references_set)(struct UX_SLAVE_CLASS_PIMA_STRUCT *pima, ULONG object_handle, UCHAR *object_handle_array, ULONG object_handle_array_length); + VOID *ux_device_class_pima_parameter_application; + + +} UX_SLAVE_CLASS_PIMA_PARAMETER; + + +/* Define PIMA Object decompaction structure. */ + +#define UX_DEVICE_CLASS_PIMA_OBJECT_MAX_LENGTH 512 +#define UX_DEVICE_CLASS_PIMA_OBJECT_VARIABLE_OFFSET 52 +#define UX_DEVICE_CLASS_PIMA_OBJECT_ENTRIES 15 + + +/* Define PIMA storage decompaction structure. */ + +#define UX_DEVICE_CLASS_PIMA_STORAGE_TYPE (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 0 ) +#define UX_DEVICE_CLASS_PIMA_STORAGE_FILE_SYSTEM_TYPE (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 2 ) +#define UX_DEVICE_CLASS_PIMA_STORAGE_ACCESS_CAPABILITY (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 4 ) +#define UX_DEVICE_CLASS_PIMA_STORAGE_MAX_CAPACITY_LOW (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 6 ) +#define UX_DEVICE_CLASS_PIMA_STORAGE_MAX_CAPACITY_HIGH (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 10) +#define UX_DEVICE_CLASS_PIMA_STORAGE_FREE_SPACE_LOW (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 14) +#define UX_DEVICE_CLASS_PIMA_STORAGE_FREE_SPACE_HIGH (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 18) +#define UX_DEVICE_CLASS_PIMA_STORAGE_FREE_SPACE_IMAGE (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 22) +#define UX_DEVICE_CLASS_PIMA_STORAGE_FREE_STORAGE_DESCRIPTION (UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + 26) + +/* Define Pima Class function prototypes. */ +UINT _ux_device_class_pima_initialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_pima_activate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_pima_deactivate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_pima_control_request(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_pima_device_info_send(UX_SLAVE_CLASS_PIMA *pima); +UINT _ux_device_class_pima_entry(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_pima_event_get(UX_SLAVE_CLASS_PIMA *pima, + UX_SLAVE_CLASS_PIMA_EVENT *pima_event); +UINT _ux_device_class_pima_event_set(UX_SLAVE_CLASS_PIMA *pima, + UX_SLAVE_CLASS_PIMA_EVENT *pima_event); +VOID _ux_device_class_pima_interrupt_thread(ULONG pima_class); +UINT _ux_device_class_pima_response_send(UX_SLAVE_CLASS_PIMA *pima, ULONG response_code, + ULONG number_parameters, + ULONG parameter_1, ULONG parameter_2, ULONG paramater_3); +VOID _ux_device_class_pima_thread(ULONG pima_class); +UINT _ux_device_class_pima_object_handles_send(UX_SLAVE_CLASS_PIMA *pima, + ULONG storage_id, + ULONG object_format_code, + ULONG object_association); +UINT _ux_device_class_pima_objects_number_send(UX_SLAVE_CLASS_PIMA *pima, + ULONG storage_id, + ULONG object_format_code, + ULONG object_association); + +UINT _ux_device_class_pima_device_prop_desc_get(UX_SLAVE_CLASS_PIMA *pima, ULONG device_property_code); +UINT _ux_device_class_pima_device_prop_value_get(UX_SLAVE_CLASS_PIMA *pima, ULONG device_property_code); +UINT _ux_device_class_pima_device_prop_value_set(UX_SLAVE_CLASS_PIMA *pima, ULONG device_property_code); +UINT _ux_device_class_pima_object_info_get(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle); +UINT _ux_device_class_pima_object_info_send(UX_SLAVE_CLASS_PIMA *pima, ULONG storage_id, ULONG parent_object_handle); +UINT _ux_device_class_pima_object_data_get(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle); +UINT _ux_device_class_pima_object_data_send(UX_SLAVE_CLASS_PIMA *pima); +UINT _ux_device_class_pima_object_delete(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle); +UINT _ux_device_class_pima_object_add(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle); +UINT _ux_device_class_pima_partial_object_data_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle, + ULONG offset_requested, + ULONG length_requested); + +UINT _ux_device_class_pima_storage_id_send(UX_SLAVE_CLASS_PIMA *pima); +UINT _ux_device_class_pima_storage_info_get(UX_SLAVE_CLASS_PIMA *pima, ULONG storage_id); +UINT _ux_device_class_pima_object_props_supported_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_format_code); +UINT _ux_device_class_pima_object_prop_value_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle, + ULONG object_property_code); +UINT _ux_device_class_pima_object_prop_value_set(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle, + ULONG object_property_code); +UINT _ux_device_class_pima_object_prop_desc_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_property, + ULONG object_format_code); +UINT _ux_device_class_pima_object_references_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle); +UINT _ux_device_class_pima_object_references_set(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle); +UINT _ux_device_class_pima_object_prop_value_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle, + ULONG object_property_code); +UINT _ux_device_class_pima_object_prop_value_set(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle, + ULONG object_property_code); +UINT _ux_device_class_pima_storage_format(UX_SLAVE_CLASS_PIMA *pima, ULONG storage_id); +UINT _ux_device_class_pima_device_reset(UX_SLAVE_CLASS_PIMA *pima); + +/* Define Device PIMA Class API prototypes. */ + +#define ux_device_class_pima_initialize _ux_device_class_pima_initialize +#define ux_device_class_pima_activate _ux_device_class_pima_activate +#define ux_device_class_pima_dectivate _ux_device_class_pima_dectivate +#define ux_device_class_pima_entry _ux_device_class_pima_entry +#define ux_device_class_pima_control_request _ux_device_class_pima_control_request +#define ux_device_class_pima_object_add _ux_device_class_pima_object_add + +/* Define Pima Class data prototypes. */ + +extern UCHAR _ux_device_class_pima_vendor_extension_descriptor[]; +extern USHORT _ux_device_class_pima_supported_operations[]; +extern USHORT _ux_device_class_pima_supported_events[]; +extern USHORT _ux_device_class_pima_supported_capture_formats[]; +extern USHORT _ux_device_class_pima_supported_image_formats[]; +extern USHORT _ux_device_class_pima_device_prop_supported[]; + + + +#endif diff --git a/common/usbx_device_classes/inc/ux_device_class_rndis.h b/common/usbx_device_classes/inc/ux_device_class_rndis.h new file mode 100644 index 0000000..c934b18 --- /dev/null +++ b/common/usbx_device_classes/inc/ux_device_class_rndis.h @@ -0,0 +1,570 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_rndis.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the equivalences for the USBX Device Class RNDIS */ +/* component. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_RNDIS_H +#define UX_DEVICE_CLASS_RNDIS_H + +#include "nx_api.h" +#include "ux_network_driver.h" + +/* Define generic RNDIS equivalences. */ +#define UX_DEVICE_CLASS_RNDIS_CLASS_COMMUNICATION_CONTROL 0x02 +#define UX_DEVICE_CLASS_RNDIS_CLASS_COMMUNICATION_DATA 0x0A +#define UX_DEVICE_CLASS_RNDIS_NEW_INTERRUPT_EVENT 1 +#define UX_DEVICE_CLASS_RNDIS_NEW_BULKOUT_EVENT 2 +#define UX_DEVICE_CLASS_RNDIS_NEW_BULKIN_EVENT 4 +#define UX_DEVICE_CLASS_RNDIS_NEW_DEVICE_STATE_CHANGE_EVENT 8 +#define UX_DEVICE_CLASS_RNDIS_INTERRUPT_RESPONSE_LENGTH 8 +#define UX_DEVICE_CLASS_RNDIS_INTERRUPT_RESPONSE_AVAILABLE_FLAG 1 +#define UX_DEVICE_CLASS_RNDIS_BASE_IP_ADDRESS 0xC0A80001 +#define UX_DEVICE_CLASS_RNDIS_BASE_IP_MASK 0xFFFFFF00 +#define UX_DEVICE_CLASS_RNDIS_MAX_MTU 1518 +#define UX_DEVICE_CLASS_RNDIS_ETHERNET_IP 0x0800 +#define UX_DEVICE_CLASS_RNDIS_ETHERNET_ARP 0x0806 +#define UX_DEVICE_CLASS_RNDIS_ETHERNET_RARP 0x8035 +#define UX_DEVICE_CLASS_RNDIS_ETHERNET_PACKET_SIZE 1536 +#define UX_DEVICE_CLASS_RNDIS_NX_ALIGN_PADDING 2 +#define UX_DEVICE_CLASS_RNDIS_NX_PKPOOL_ENTRIES 8 + +#define UX_DEVICE_CLASS_RNDIS_NX_PACKET_SIZE sizeof(NX_PACKET) + +#define UX_DEVICE_CLASS_RNDIS_NX_PAYLOAD_SIZE_ASSERT UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG(UX_DEVICE_CLASS_RNDIS_ETHERNET_PACKET_SIZE, UX_DEVICE_CLASS_RNDIS_NX_ALIGN_PADDING), UX_DEVICE_CLASS_RNDIS_NX_PAYLOAD_SIZE_calc_ovf) +#define UX_DEVICE_CLASS_RNDIS_NX_PAYLOAD_SIZE (UX_DEVICE_CLASS_RNDIS_ETHERNET_PACKET_SIZE + UX_DEVICE_CLASS_RNDIS_NX_ALIGN_PADDING) + +#define UX_DEVICE_CLASS_RNDIS_NX_BUFF_SIZE_ASSERT \ + UX_DEVICE_CLASS_RNDIS_NX_PAYLOAD_SIZE_ASSERT \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG( \ + UX_DEVICE_CLASS_RNDIS_NX_PAYLOAD_SIZE, \ + UX_DEVICE_CLASS_RNDIS_NX_PACKET_SIZE), \ + UX_DEVICE_CLASS_RNDIS_NX_BUFF_SIZE_calc_ovf) +#define UX_DEVICE_CLASS_RNDIS_NX_BUFF_SIZE (UX_DEVICE_CLASS_RNDIS_NX_PAYLOAD_SIZE + UX_DEVICE_CLASS_RNDIS_NX_PACKET_SIZE) + +#define UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT \ + UX_DEVICE_CLASS_RNDIS_NX_BUFF_SIZE_ASSERT \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG( \ + UX_DEVICE_CLASS_RNDIS_NX_PKPOOL_ENTRIES, \ + UX_DEVICE_CLASS_RNDIS_NX_BUFF_SIZE), \ + UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE_calc1_ovf) \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG( \ + UX_DEVICE_CLASS_RNDIS_NX_PKPOOL_ENTRIES * \ + UX_DEVICE_CLASS_RNDIS_NX_BUFF_SIZE, \ + 32), UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE_calc2_ovf) +#define UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE (UX_DEVICE_CLASS_RNDIS_NX_PKPOOL_ENTRIES * UX_DEVICE_CLASS_RNDIS_NX_BUFF_SIZE + 32) + +#define UX_DEVICE_CLASS_RNDIS_ETHERNET_SIZE 14 +#define UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH 6 +#define UX_DEVICE_CLASS_RNDIS_VENDOR_DESCRIPTION_MAX_LENGTH 64 +#define UX_DEVICE_CLASS_RNDIS_MAC_OPTIONS 8 +#define UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG 1 + +#define UX_DEVICE_CLASS_RNDIS_OID_SUPPORTED_LIST_LENGTH 30 + +/* Device RNDIS Requests */ +#define UX_DEVICE_CLASS_RNDIS_SEND_ENCAPSULATED_COMMAND 0x00 +#define UX_DEVICE_CLASS_RNDIS_GET_ENCAPSULATED_RESPONSE 0x01 + +/* Define RNDIS Versions. Set to 1.0 here. */ +#define UX_DEVICE_CLASS_RNDIS_VERSION_MAJOR 0x00000001 +#define UX_DEVICE_CLASS_RNDIS_VERSION_MINOR 0x00000000 + +/* Define RNDIS Conection type supported. Set to conectionless. */ +#define UX_DEVICE_CLASS_RNDIS_DF_CONNECTIONLESS 0x00000001 +#define UX_DEVICE_CLASS_RNDIS_DF_CONNECTION_ORIENTED 0x00000002 +#define UX_DEVICE_CLASS_RNDIS_DF_CONNECTION_SUPPORTED UX_DEVICE_CLASS_RNDIS_DF_CONNECTIONLESS + +/* Define RNDIS Medium supported by the device. */ +#define UX_DEVICE_CLASS_RNDIS_MEDIUM_SUPPORTED 0x00000000 + +/* Define RNDIS Packet size and types supported. */ +#define UX_DEVICE_CLASS_RNDIS_MAX_PACKET_PER_TRANSFER 0x00000001 +#define UX_DEVICE_CLASS_RNDIS_MAX_PACKET_TRANSFER_SIZE 0x00000640 +#define UX_DEVICE_CLASS_RNDIS_PACKET_ALIGNEMENT_FACTOR 0x00000003 +#define UX_DEVICE_CLASS_RNDIS_MAX_FRAME_SIZE 0x000005DC +#define UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH 0x000005EA + +/* Define LINK speeds. */ +#define UX_DEVICE_CLASS_RNDIS_LINK_SPEED_FS 0x0001D4C0 + +/* Define LINK statess. */ +#define UX_DEVICE_CLASS_RNDIS_LINK_STATE_DOWN 0 +#define UX_DEVICE_CLASS_RNDIS_LINK_STATE_UP 1 +#define UX_DEVICE_CLASS_RNDIS_LINK_STATE_PENDING_UP 2 +#define UX_DEVICE_CLASS_RNDIS_LINK_STATE_PENDING_DOWN 3 + +/* Define media connection values. */ +#define UX_DEVICE_CLASS_RNDIS_MEDIA_CONNECTED 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_MEDIA_DISCONNECTED 0x00000001 + +/* Define media supported values. */ +#define UX_DEVICE_CLASS_RNDIS_MEDIA_802_3 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_MEDIA_802_5 0x00000001 +#define UX_DEVICE_CLASS_RNDIS_MEDIA_FDDI 0x00000002 +#define UX_DEVICE_CLASS_RNDIS_MEDIA_WAN 0x00000003 +#define UX_DEVICE_CLASS_RNDIS_MEDIA_LOCAL_TALK 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_MEDIA_DIX 0x00000005 +#define UX_DEVICE_CLASS_RNDIS_MEDIA_ARCNET_RAW 0x00000006 +#define UX_DEVICE_CLASS_RNDIS_MEDIA_ARCNET_878_2 0x00000007 +#define UX_DEVICE_CLASS_RNDIS_MEDIA_ATM 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_MEDIA_WIRELESS_WAN 0x00000009 +#define UX_DEVICE_CLASS_RNDIS_MEDIA_IRDA 0x0000000A + +/* Define RNDIS status values. */ +#define UX_DEVICE_CLASS_RNDIS_STATUS_SUCCESS 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_STATUS_FAILURE 0xC0000001 +#define UX_DEVICE_CLASS_RNDIS_STATUS_INVALID_DATA 0xC0010015 +#define UX_DEVICE_CLASS_RNDIS_STATUS_NOT_SUPPORTED 0xC00000BB +#define UX_DEVICE_CLASS_RNDIS_STATUS_MEDIA_CONNECTED 0x4001000B +#define UX_DEVICE_CLASS_RNDIS_STATUS_MEDIA_DISCONNECT 0x4001000C + +/* Define RNDIS Control Messages values. */ +#define UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE 0x00000002 +#define UX_DEVICE_CLASS_RNDIS_MSG_HALT 0x00000003 +#define UX_DEVICE_CLASS_RNDIS_MSG_QUERY 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_MSG_SET 0x00000005 +#define UX_DEVICE_CLASS_RNDIS_MSG_RESET 0x00000006 +#define UX_DEVICE_CLASS_RNDIS_MSG_INDICATE_STATUS 0x00000007 +#define UX_DEVICE_CLASS_RNDIS_MSG_KEEP_ALIVE 0x00000008 + +/* Define RNDIS Control Completion values. */ +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE 0x80000002 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY 0x80000004 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_SET 0x80000005 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_RESET 0x80000006 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE 0x80000008 + +/* Define RNDIS Control Messages : MSG_INITIALIZE offsets. */ +#define UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE_REQUEST_ID 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE_MAJOR_VERSION 0x0000000C +#define UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE_MINOR_VERSION 0x00000010 +#define UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE_MAX_TRANSFER_SIZE 0x00000014 + +/* Define RNDIS Control Messages : CMPLT_INITIALIZE offsets. */ +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_REQUEST_ID 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_STATUS 0x0000000C +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MAJOR_VERSION 0x00000010 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MINOR_VERSION 0x00000014 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_DEVICE_FLAGS 0x00000018 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MEDIUM 0x0000001C +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MAX_PACKETS_PER_TRANSFER 0x00000020 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MAX_TRANSFER_SIZE 0x00000024 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_PACKET_ALIGNMENT 0x00000028 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_AFL_LIST_OFFSET 0x0000002C +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_AFL_LIST_SIZE 0x00000030 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_RESPONSE_LENGTH 0x00000034 + +/* Define RNDIS Control Messages : MSG_HALT offsets. */ +#define UX_DEVICE_CLASS_RNDIS_MSG_HALT_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_MSG_HALT_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_MSG_HALT_REQUEST_ID 0x00000008 + +/* Define RNDIS Control Messages : MSG_QUERY offsets. */ +#define UX_DEVICE_CLASS_RNDIS_MSG_QUERY_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_MSG_QUERY_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_MSG_QUERY_REQUEST_ID 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_MSG_QUERY_OID 0x0000000C +#define UX_DEVICE_CLASS_RNDIS_MSG_QUERY_INFO_BUFFER_LENGTH 0x00000010 +#define UX_DEVICE_CLASS_RNDIS_MSG_QUERY_INFO_BUFFER_OFFSET 0x00000014 +#define UX_DEVICE_CLASS_RNDIS_MSG_QUERY_DEVICE_VC_HANDLE 0x00000018 + +#define UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_REQUEST_ID 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_STATUS 0x0000000C +#define UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER_LENGTH 0x00000010 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER_OFFSET 0x00000014 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER 0x00000018 + +/* Define RNDIS Control Messages : MSG_SET offsets. */ +#define UX_DEVICE_CLASS_RNDIS_MSG_SET_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_MSG_SET_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_MSG_SET_REQUEST_ID 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_MSG_SET_OID 0x0000000C +#define UX_DEVICE_CLASS_RNDIS_MSG_SET_INFO_BUFFER_LENGTH 0x00000010 +#define UX_DEVICE_CLASS_RNDIS_MSG_SET_INFO_BUFFER_OFFSET 0x00000014 +#define UX_DEVICE_CLASS_RNDIS_MSG_SET_DEVICE_VC_HANDLE 0x00000018 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_SET_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_SET_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_SET_REQUEST_ID 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_SET_STATUS 0x0000000C +#define UX_DEVICE_CLASS_RNDIS_CMPLT_SET_RESPONSE_LENGTH 0x00000010 + +/* Define RNDIS Control Messages : MSG_RESET offsets. */ +#define UX_DEVICE_CLASS_RNDIS_MSG_RESET_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_MSG_RESET_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_MSG_RESET_RESERVED 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_STATUS 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_ADDRESSING_RESET 0x0000000C +#define UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_RESPONSE_LENGTH 0x00000010 + +/* Define RNDIS Control Messages : MSG_INDICATE_STATUS offsets. */ +#define UX_DEVICE_CLASS_RNDIS_MSG_INDICATE_STATUS_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_MSG_INDICATE_STATUS_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_MSG_INDICATE_STATUS_STATUS 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_MSG_INDICATE_STATUS_STATUS_BUFFER_LENGTH 0x0000000C +#define UX_DEVICE_CLASS_RNDIS_MSG_INDICATE_STATUS_STATUS_BUFFER_OFFSET 0x00000010 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INDICATE_STATUS_DIAG 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_INDICATE_STATUS_ERROR_OFFSET 0x00000004 + +/* Define RNDIS Control Messages : MSG_KEEP_ALIVE offsets. */ +#define UX_DEVICE_CLASS_RNDIS_MSG_KEEP_ALIVE_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_MSG_KEEP_ALIVE_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_MSG_KEEP_ALIVE_REQUEST_ID 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_REQUEST_ID 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_STATUS 0x0000000C +#define UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_RESPONSE_LENGTH 0x00000010 + +/* Define RNDIS State machine. */ +#define UX_DEVICE_CLASS_RNDIS_STATE_UNINITIALIZED 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_STATE_INITIALIZED 0x00000001 +#define UX_DEVICE_CLASS_RNDIS_STATE_DATA_INITIALIZED 0x00000002 + +/* Define Required Object IDs (OIDs) */ +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_SUPPORTED_LIST 0x00010101 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_HARDWARE_STATUS 0x00010102 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_IN_USE 0x00010104 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_LOOKAHEAD 0x00010105 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE 0x00010106 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_LINK_SPEED 0x00010107 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_TRANSMIT_BUFFER_SPACE 0x00010108 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_RECEIVE_BUFFER_SPACE 0x00010109 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE 0x0001010A +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE 0x0001010B +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_VENDOR_ID 0x0001010C +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_VENDOR_DESCRIPTION 0x0001010D +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_CURRENT_PACKET_FILTER 0x0001010E +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_CURRENT_LOOKAHEAD 0x0001010F +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_DRIVER_VERSION 0x00010110 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE 0x00010111 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_PROTOCOL_OPTIONS 0x00010112 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MAC_OPTIONS 0x00010113 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_CONNECT_STATUS 0x00010114 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_SEND_PACKETS 0x00010115 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_VENDOR_DRIVER_VERSION 0x00010116 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_SUPPORTED_GUIDS 0x00010117 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_NETWORK_LAYER_ADDRESSES 0x00010118 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_TRANSPORT_HEADER_OFFSET 0x00010119 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MACHINE_NAME 0x0001021A +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER 0x0001021B +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_VLAN_ID 0x0001021C + +/* Define Optional OIDs */ +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_CAPABILITIES 0x00010201 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_PHYSICAL_MEDIUM 0x00010202 + +/* Define Required statistics OIDs */ +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_XMIT_OK 0x00020101 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_OK 0x00020102 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_XMIT_ERROR 0x00020103 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_ERROR 0x00020104 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_NO_BUFFER 0x00020105 + +/* Define Optional statistics OIDs */ +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_DIRECTED_BYTES_RCV 0x00020207 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MULTICAST_BYTES_RCV 0x00020209 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_BROADCAST_BYTES_RCV 0x0002020B +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_CRC_ERROR 0x0002020D +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_GET_TIME_CAPS 0x0002020F +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_GET_NETCARD_TIME 0x00020210 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_NETCARD_LOAD 0x00020211 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_DEVICE_PROFILE 0x00020212 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_INIT_TIME_MS 0x00020213 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_RESET_COUNTS 0x00020214 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_SENSE_COUNTS 0x00020215 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_FRIENDLY_NAME 0x00020216 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_MINIPORT_INFO 0x00020217 +#define UX_DEVICE_CLASS_RNDIS_OID_GEN_RESET_VERIFY_PARAMETERS 0x00020218 + +/* Define IEEE 802.3 (Ethernet) OIDs */ + +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_PERMANENT_ADDRESS 0x01010101 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_CURRENT_ADDRESS 0x01010102 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_MULTICAST_LIST 0x01010103 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_MAC_OPTIONS 0x01010105 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_XMIT_ONE_COLLISION 0x01020102 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_XMIT_DEFERRED 0x01020201 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_RCV_OVERRUN 0x01020203 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_XMIT_UNDERRUN 0x01020204 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_XMIT_HEARTBEAT_FAILURE 0x01020205 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 +#define UX_DEVICE_CLASS_RNDIS_OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 + +/* Define Hardware status code. */ +#define UX_DEVICE_CLASS_RNDIS_OID_HW_STATUS_READY 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_OID_HW_STATUS_INITIALIZING 0x00000001 +#define UX_DEVICE_CLASS_RNDIS_OID_HW_STATUS_RESET 0x00000002 +#define UX_DEVICE_CLASS_RNDIS_OID_HW_STATUS_CLOSING 0x00000003 +#define UX_DEVICE_CLASS_RNDIS_OID_HW_STATUS_NOT_READY 0x00000004 + +/* Define RNDIS Packet Header format. */ +#define UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE 0x00000000 +#define UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_LENGTH 0x00000004 +#define UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET 0x00000008 +#define UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH 0x0000000C +#define UX_DEVICE_CLASS_RNDIS_PACKET_OOB_DATA_OFFSET 0x00000010 +#define UX_DEVICE_CLASS_RNDIS_PACKET_OOB_DATA_LENGTH 0x00000014 +#define UX_DEVICE_CLASS_RNDIS_PACKET_NUM_OOB_DATA_ELEMENTS 0x00000018 +#define UX_DEVICE_CLASS_RNDIS_PACKET_INFO_OFFSET 0x0000001C +#define UX_DEVICE_CLASS_RNDIS_PACKET_INFO_LENGTH 0x00000020 +#define UX_DEVICE_CLASS_RNDIS_PACKET_VC_HANDLE 0x00000024 +#define UX_DEVICE_CLASS_RNDIS_PACKET_RESERVED 0x00000028 +#define UX_DEVICE_CLASS_RNDIS_PACKET_BUFFER 0x0000002C +#define UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH 0x0000002C + +/* Define NetX errors inside the RNDIS class. */ +#define UX_DEVICE_CLASS_RNDIS_NX_SUCCESS 0x00 +#define UX_DEVICE_CLASS_RNDIS_NX_NO_PACKET 0x01 +#define UX_DEVICE_CLASS_RNDIS_NX_UNDERFLOW 0x02 +#define UX_DEVICE_CLASS_RNDIS_NX_OVERFLOW 0x03 +#define UX_DEVICE_CLASS_RNDIS_NX_NO_MAPPING 0x04 +#define UX_DEVICE_CLASS_RNDIS_NX_DELETED 0x05 +#define UX_DEVICE_CLASS_RNDIS_NX_POOL_ERROR 0x06 +#define UX_DEVICE_CLASS_RNDIS_NX_PTR_ERROR 0x07 +#define UX_DEVICE_CLASS_RNDIS_NX_WAIT_ERROR 0x08 +#define UX_DEVICE_CLASS_RNDIS_NX_SIZE_ERROR 0x09 +#define UX_DEVICE_CLASS_RNDIS_NX_OPTION_ERROR 0x0a +#define UX_DEVICE_CLASS_RNDIS_NX_DELETE_ERROR 0x10 +#define UX_DEVICE_CLASS_RNDIS_NX_CALLER_ERROR 0x11 +#define UX_DEVICE_CLASS_RNDIS_NX_INVALID_PACKET 0x12 +#define UX_DEVICE_CLASS_RNDIS_NX_INVALID_SOCKET 0x13 +#define UX_DEVICE_CLASS_RNDIS_NX_NOT_ENABLED 0x14 +#define UX_DEVICE_CLASS_RNDIS_NX_ALREADY_ENABLED 0x15 +#define UX_DEVICE_CLASS_RNDIS_NX_ENTRY_NOT_FOUND 0x16 +#define UX_DEVICE_CLASS_RNDIS_NX_NO_MORE_ENTRIES 0x17 +#define UX_DEVICE_CLASS_RNDIS_NX_ARP_TIMER_ERROR 0x18 +#define UX_DEVICE_CLASS_RNDIS_NX_RESERVED_CODE0 0x19 +#define UX_DEVICE_CLASS_RNDIS_NX_WAIT_ABORTED 0x1A +#define UX_DEVICE_CLASS_RNDIS_NX_IP_INTERNAL_ERROR 0x20 +#define UX_DEVICE_CLASS_RNDIS_NX_IP_ADDRESS_ERROR 0x21 +#define UX_DEVICE_CLASS_RNDIS_NX_ALREADY_BOUND 0x22 +#define UX_DEVICE_CLASS_RNDIS_NX_PORT_UNAVAILABLE 0x23 +#define UX_DEVICE_CLASS_RNDIS_NX_NOT_BOUND 0x24 +#define UX_DEVICE_CLASS_RNDIS_NX_RESERVED_CODE1 0x25 +#define UX_DEVICE_CLASS_RNDIS_NX_SOCKET_UNBOUND 0x26 +#define UX_DEVICE_CLASS_RNDIS_NX_NOT_CREATED 0x27 +#define UX_DEVICE_CLASS_RNDIS_NX_SOCKETS_BOUND 0x28 +#define UX_DEVICE_CLASS_RNDIS_NX_NO_RESPONSE 0x29 +#define UX_DEVICE_CLASS_RNDIS_NX_POOL_DELETED 0x30 +#define UX_DEVICE_CLASS_RNDIS_NX_ALREADY_RELEASED 0x31 +#define UX_DEVICE_CLASS_RNDIS_NX_RESERVED_CODE2 0x32 +#define UX_DEVICE_CLASS_RNDIS_NX_MAX_LISTEN 0x33 +#define UX_DEVICE_CLASS_RNDIS_NX_DUPLICATE_LISTEN 0x34 +#define UX_DEVICE_CLASS_RNDIS_NX_NOT_CLOSED 0x35 +#define UX_DEVICE_CLASS_RNDIS_NX_NOT_LISTEN_STATE 0x36 +#define UX_DEVICE_CLASS_RNDIS_NX_IN_PROGRESS 0x37 +#define UX_DEVICE_CLASS_RNDIS_NX_NOT_CONNECTED 0x38 +#define UX_DEVICE_CLASS_RNDIS_NX_WINDOW_OVERFLOW 0x39 +#define UX_DEVICE_CLASS_RNDIS_NX_ALREADY_SUSPENDED 0x40 +#define UX_DEVICE_CLASS_RNDIS_NX_DISCONNECT_FAILED 0x41 +#define UX_DEVICE_CLASS_RNDIS_NX_STILL_BOUND 0x42 +#define UX_DEVICE_CLASS_RNDIS_NX_NOT_SUCCESSFUL 0x43 +#define UX_DEVICE_CLASS_RNDIS_NX_UNHANDLED_COMMAND 0x44 +#define UX_DEVICE_CLASS_RNDIS_NX_NO_FREE_PORTS 0x45 +#define UX_DEVICE_CLASS_RNDIS_NX_INVALID_PORT 0x46 +#define UX_DEVICE_CLASS_RNDIS_NX_INVALID_RELISTEN 0x47 +#define UX_DEVICE_CLASS_RNDIS_NX_CONNECTION_PENDING 0x48 +#define UX_DEVICE_CLASS_RNDIS_NX_TX_QUEUE_DEPTH 0x49 +#define UX_DEVICE_CLASS_RNDIS_NX_NOT_IMPLEMENTED 0x80 + +/* Define timeout packet allocation value. */ +#ifndef UX_DEVICE_CLASS_RNDIS_PACKET_POOL_WAIT +#define UX_DEVICE_CLASS_RNDIS_PACKET_POOL_WAIT 10 +#endif + +/* Calculate response buffer length. */ +#define UX_DEVICE_CLASS_RNDIS_OID_SUPPORTED_RESPONSE_LENGTH (UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER + UX_DEVICE_CLASS_RNDIS_OID_SUPPORTED_LIST_LENGTH * 4) +#define UX_DEVICE_CLASS_RNDIS_VENDOR_DESCRIPTION_MAX_RESPONSE_LENGTH (UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER + UX_DEVICE_CLASS_RNDIS_VENDOR_DESCRIPTION_MAX_LENGTH) +#define UX_DEVICE_CLASS_RNDIS_NODE_ID_RESPONSE_LENGTH (UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER + UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH) + +/* Decide maximun size of RNDIS response buffer (with 1 ~ 4 bytes as padding and aligned to 4 bytes). */ +#define UX_DEVICE_CLASS_RNDIS_MAX(a, b) (((a) > (b)) ? (a) : (b)) +#define UX_DEVICE_CLASS_RNDIS_MAX_CONTROL_RESPONSE_LENGTH ((( \ + UX_DEVICE_CLASS_RNDIS_MAX(UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_RESPONSE_LENGTH, \ + UX_DEVICE_CLASS_RNDIS_MAX(UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_RESPONSE_LENGTH, \ + UX_DEVICE_CLASS_RNDIS_MAX(UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_RESPONSE_LENGTH, \ + UX_DEVICE_CLASS_RNDIS_MAX(UX_DEVICE_CLASS_RNDIS_CMPLT_SET_RESPONSE_LENGTH, \ + UX_DEVICE_CLASS_RNDIS_MAX(UX_DEVICE_CLASS_RNDIS_OID_SUPPORTED_RESPONSE_LENGTH, \ + UX_DEVICE_CLASS_RNDIS_MAX(UX_DEVICE_CLASS_RNDIS_VENDOR_DESCRIPTION_MAX_RESPONSE_LENGTH, \ + UX_DEVICE_CLASS_RNDIS_NODE_ID_RESPONSE_LENGTH))))))) & (~0x3)) + 0x4) + +/* Ensure maximum-sized RNDIS response can fit in the control endpoint's transfer buffer. */ +#if UX_DEVICE_CLASS_RNDIS_MAX_CONTROL_RESPONSE_LENGTH > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH +#error "Error: the maximum-sized RNDIS response cannot fit inside the control endpoint's data buffer. Increase UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH." +#endif + +/* Define Slave RNDIS Class Calling Parameter structure */ + +typedef struct UX_SLAVE_CLASS_RNDIS_PARAMETER_STRUCT +{ + VOID (*ux_slave_class_rndis_instance_activate)(VOID *); + VOID (*ux_slave_class_rndis_instance_deactivate)(VOID *); + ULONG ux_slave_class_rndis_parameter_media; + ULONG ux_slave_class_rndis_parameter_vendor_id; + ULONG ux_slave_class_rndis_parameter_driver_version; + UCHAR ux_slave_class_rndis_parameter_vendor_description[UX_DEVICE_CLASS_RNDIS_VENDOR_DESCRIPTION_MAX_LENGTH]; + UCHAR ux_slave_class_rndis_parameter_local_node_id[UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH]; + UCHAR ux_slave_class_rndis_parameter_remote_node_id[UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH]; + NX_IP *ux_slave_class_rndis_parameter_nx_ip; + ULONG ux_slave_class_rndis_parameter_nx_ip_address; + ULONG ux_slave_class_rndis_parameter_nx_ip_network_mask; + +} UX_SLAVE_CLASS_RNDIS_PARAMETER; + +/* Define RNDIS Class structure. */ + +typedef struct UX_SLAVE_CLASS_RNDIS_STRUCT +{ + UX_SLAVE_INTERFACE *ux_slave_class_rndis_interface; + UX_SLAVE_CLASS_RNDIS_PARAMETER ux_slave_class_rndis_parameter; + TX_SEMAPHORE ux_slave_class_rndis_semaphore; + UX_SLAVE_ENDPOINT *ux_slave_class_rndis_interrupt_endpoint; + UX_SLAVE_ENDPOINT *ux_slave_class_rndis_bulkin_endpoint; + UX_SLAVE_ENDPOINT *ux_slave_class_rndis_bulkout_endpoint; + UCHAR ux_slave_class_rndis_response[UX_DEVICE_CLASS_RNDIS_MAX_CONTROL_RESPONSE_LENGTH]; + ULONG ux_slave_class_rndis_response_length; + ULONG ux_slave_class_rndis_state; + ULONG ux_slave_class_rndis_major_version; + ULONG ux_slave_class_rndis_minor_version; + ULONG ux_slave_class_rndis_max_transfer_size; + ULONG ux_slave_class_rndis_request_id; + ULONG ux_slave_class_rndis_statistics_xmit_ok; + ULONG ux_slave_class_rndis_statistics_rcv_ok; + ULONG ux_slave_class_rndis_statistics_xmit_error; + ULONG ux_slave_class_rndis_statistics_rcv_error; + ULONG ux_slave_class_rndis_statistics_rcv_no_buffer; + ULONG ux_slave_class_rndis_statistics_rcv_error_alignment; + ULONG ux_slave_class_rndis_statistics_xmit_one_collision; + ULONG ux_slave_class_rndis_statistics_xmit_more_collisions; + TX_EVENT_FLAGS_GROUP ux_slave_class_rndis_event_flags_group; + UCHAR ux_slave_class_rndis_local_node_id[UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH]; + UCHAR ux_slave_class_rndis_remote_node_id[UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH]; + NX_IP *ux_slave_class_rndis_nx_ip; + ULONG ux_slave_class_rndis_nx_ip_address; + ULONG ux_slave_class_rndis_nx_ip_network_mask; + NX_INTERFACE *ux_slave_class_rndis_nx_interface; + NX_PACKET *ux_slave_class_rndis_xmit_queue; + NX_PACKET *ux_slave_class_rndis_receive_queue; + UCHAR *ux_slave_class_rndis_pool_memory; + NX_PACKET_POOL ux_slave_class_rndis_packet_pool; + TX_THREAD ux_slave_class_rndis_interrupt_thread; + TX_THREAD ux_slave_class_rndis_bulkin_thread; + TX_THREAD ux_slave_class_rndis_bulkout_thread; + UCHAR *ux_slave_class_rndis_interrupt_thread_stack; + UCHAR *ux_slave_class_rndis_bulkin_thread_stack; + UCHAR *ux_slave_class_rndis_bulkout_thread_stack; + ULONG ux_slave_class_rndis_link_state; + TX_MUTEX ux_slave_class_rndis_mutex; + VOID *ux_slave_class_rndis_network_handle; + +} UX_SLAVE_CLASS_RNDIS; + + +/* Requests - Ethernet Networking Control Model */ + +#define UX_DEVICE_CLASS_RNDIS_SEND_ENCAPSULATED_COMMAND 0x00 + /* Issues a command in the format of the supported control + protocol. The intent of this mechanism is to support + networking devices (e.g., host-based cable modems) + that require an additional vendor-defined interface for + media specific hardware configuration and + management. */ +#define UX_DEVICE_CLASS_RNDIS_GET_ENCAPSULATED_RESPONSE 0x01 + /* Requests a response in the format of the supported + control protocol. */ + + +/* Define buffer length for IN/OUT pipes. */ + +#define UX_DEVICE_CLASS_RNDIS_BUFFER_SIZE 4096 + + +/* Define Device RNDIS Class prototypes. */ + +UINT _ux_device_class_rndis_activate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_rndis_control_request(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_rndis_deactivate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_rndis_entry(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_rndis_initialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_rndis_write(VOID *rndis_class, NX_PACKET *packet); +UINT _ux_device_class_rndis_msg_query(UX_SLAVE_CLASS_RNDIS *rndis, UX_SLAVE_TRANSFER *transfer_request); +UINT _ux_device_class_rndis_msg_reset(UX_SLAVE_CLASS_RNDIS *rndis, UX_SLAVE_TRANSFER *transfer_request); +UINT _ux_device_class_rndis_msg_set(UX_SLAVE_CLASS_RNDIS *rndis, UX_SLAVE_TRANSFER *transfer_request); +UINT _ux_device_class_rndis_msg_initialize(UX_SLAVE_CLASS_RNDIS *rndis, UX_SLAVE_TRANSFER *transfer_request); +UINT _ux_device_class_rndis_msg_keep_alive(UX_SLAVE_CLASS_RNDIS *rndis, UX_SLAVE_TRANSFER *transfer_request); +VOID _ux_device_class_rndis_interrupt_thread(ULONG rndis_class); +VOID _ux_device_class_rndis_bulkin_thread(ULONG rndis_class); +VOID _ux_device_class_rndis_bulkout_thread(ULONG rndis_class); + + +/* Define Device RNDIS Class API prototypes. */ + +#define ux_device_class_rndis_entry _ux_device_class_rndis_entry + + +/* Define OID supported List. */ +extern ULONG ux_device_class_rndis_oid_supported_list[]; + +#endif /* UX_DEVICE_CLASS_RNDIS_H */ diff --git a/common/usbx_device_classes/inc/ux_device_class_storage.h b/common/usbx_device_classes/inc/ux_device_class_storage.h new file mode 100644 index 0000000..c1ca49b --- /dev/null +++ b/common/usbx_device_classes/inc/ux_device_class_storage.h @@ -0,0 +1,527 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_device_class_storage.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX device storage class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_DEVICE_CLASS_STORAGE_H +#define UX_DEVICE_CLASS_STORAGE_H + +/* Define User configurable Storage Class constants. */ + +#ifndef UX_MAX_SLAVE_LUN +#define UX_MAX_SLAVE_LUN 2 +#endif + +/* Define Storage Class USB Class constants. */ + +#define UX_SLAVE_CLASS_STORAGE_CLASS 8 +#define UX_SLAVE_CLASS_STORAGE_SUBCLASS_RBC 1 +#define UX_SLAVE_CLASS_STORAGE_SUBCLASS_SFF8020 2 +#define UX_SLAVE_CLASS_STORAGE_SUBCLASS_UFI 4 +#define UX_SLAVE_CLASS_STORAGE_SUBCLASS_SFF8070 5 +#define UX_SLAVE_CLASS_STORAGE_SUBCLASS_SCSI 6 +#define UX_SLAVE_CLASS_STORAGE_PROTOCOL_CBI 0 +#define UX_SLAVE_CLASS_STORAGE_PROTOCOL_CB 1 +#define UX_SLAVE_CLASS_STORAGE_PROTOCOL_BO 0x50 + +/* Define Storage Class USB MEDIA types. */ +#define UX_SLAVE_CLASS_STORAGE_MEDIA_FAT_DISK 0 +#define UX_SLAVE_CLASS_STORAGE_MEDIA_CDROM 5 +#define UX_SLAVE_CLASS_STORAGE_MEDIA_OPTICAL_DISK 7 +#define UX_SLAVE_CLASS_STORAGE_MEDIA_IOMEGA_CLICK 0x55 + + + +/* Define Storage Class SCSI command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_SCSI_TEST_READY 0x00 +#define UX_SLAVE_CLASS_STORAGE_SCSI_REQUEST_SENSE 0x03 +#define UX_SLAVE_CLASS_STORAGE_SCSI_FORMAT 0x04 +#define UX_SLAVE_CLASS_STORAGE_SCSI_INQUIRY 0x12 +#define UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT 0x1a +#define UX_SLAVE_CLASS_STORAGE_SCSI_START_STOP 0x1b +#define UX_SLAVE_CLASS_STORAGE_SCSI_PREVENT_ALLOW_MEDIA_REMOVAL 0x1e +#define UX_SLAVE_CLASS_STORAGE_SCSI_READ_FORMAT_CAPACITY 0x23 +#define UX_SLAVE_CLASS_STORAGE_SCSI_READ_CAPACITY 0x25 +#define UX_SLAVE_CLASS_STORAGE_SCSI_READ16 0x28 +#define UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16 0x2a +#define UX_SLAVE_CLASS_STORAGE_SCSI_VERIFY 0x2f +#define UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE 0x35 +#define UX_SLAVE_CLASS_STORAGE_SCSI_READ_TOC 0x43 +#define UX_SLAVE_CLASS_STORAGE_SCSI_GET_CONFIGURATION 0x46 +#define UX_SLAVE_CLASS_STORAGE_SCSI_GET_STATUS_NOTIFICATION 0x4A +#define UX_SLAVE_CLASS_STORAGE_SCSI_READ_DISK_INFORMATION 0x51 +#define UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SELECT 0x55 +#define UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE 0x5a +#define UX_SLAVE_CLASS_STORAGE_SCSI_READ32 0xa8 +#define UX_SLAVE_CLASS_STORAGE_SCSI_REPORT_KEY 0xa4 +#define UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32 0xaa +#define UX_SLAVE_CLASS_STORAGE_SCSI_GET_PERFORMANCE 0xac +#define UX_SLAVE_CLASS_STORAGE_SCSI_READ_DVD_STRUCTURE 0xad + +/* Define Storage Class SCSI command block wrapper constants. */ + +#define UX_SLAVE_CLASS_STORAGE_CBW_SIGNATURE_MASK 0x43425355 +#define UX_SLAVE_CLASS_STORAGE_CBW_SIGNATURE 0 +#define UX_SLAVE_CLASS_STORAGE_CBW_TAG 4 +#define UX_SLAVE_CLASS_STORAGE_CBW_DATA_LENGTH 8 +#define UX_SLAVE_CLASS_STORAGE_CBW_FLAGS 12 +#define UX_SLAVE_CLASS_STORAGE_CBW_LUN 13 +#define UX_SLAVE_CLASS_STORAGE_CBW_CB_LENGTH 14 +#define UX_SLAVE_CLASS_STORAGE_CBW_CB 15 +#define UX_SLAVE_CLASS_STORAGE_CBW_LENGTH 31 + + +/* Define Storage Class SCSI response status wrapper constants. */ + +#define UX_SLAVE_CLASS_STORAGE_CSW_SIGNATURE_MASK 0x53425355 +#define UX_SLAVE_CLASS_STORAGE_CSW_SIGNATURE 0 +#define UX_SLAVE_CLASS_STORAGE_CSW_TAG 4 +#define UX_SLAVE_CLASS_STORAGE_CSW_DATA_RESIDUE 8 +#define UX_SLAVE_CLASS_STORAGE_CSW_STATUS 12 +#define UX_SLAVE_CLASS_STORAGE_CSW_LENGTH 13 + + +/* Define Storage Class SCSI inquiry command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_OPERATION 0 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_LUN 1 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_PAGE_CODE 2 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_ALLOCATION_LENGTH 4 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_UFI 12 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_SBC 06 + + +/* Define Storage Class SCSI inquiry response constants. */ + +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_PERIPHERAL_TYPE 0 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_REMOVABLE_MEDIA 1 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_DATA_FORMAT 3 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_ADDITIONAL_LENGTH 4 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_VENDOR_INFORMATION 8 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_PRODUCT_ID 16 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_PRODUCT_REVISION 32 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH 36 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH_CD_ROM 0x5b + + +/* Define Storage Class SCSI start/stop command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_START_STOP_OPERATION 0 +#define UX_SLAVE_CLASS_STORAGE_START_STOP_LBUFLAGS 1 +#define UX_SLAVE_CLASS_STORAGE_START_STOP_START_BIT 4 +#define UX_SLAVE_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_UFI 12 +#define UX_SLAVE_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_SBC 6 + + +/* Define Storage Class SCSI mode sense command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_OPERATION 0 +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_LUN 1 +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PC_PAGE_CODE 2 +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_LIST_LENGTH_6 4 +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_LIST_LENGTH_10 7 +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_ALLOCATION_LENGTH_6 4 +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_ALLOCATION_LENGTH_10 7 + +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_MEDIUM_TYPE_6 1 +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_MEDIUM_TYPE_10 2 +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_HEADER_LENGTH_6 4 +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_HEADER_LENGTH_10 8 + +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_UFI 12 +#define UX_SLAVE_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_SBC 12 + + +/* Define Storage Class SCSI request sense command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_OPERATION 0 +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_LUN 1 +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_ALLOCATION_LENGTH 4 +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_COMMAND_LENGTH_UFI 12 +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_COMMAND_LENGTH_SBC 12 + + +/* Define Storage Class request sense response constants. */ + +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ERROR_CODE 0 +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_SENSE_KEY 2 +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_INFORMATION 3 +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ADD_LENGTH 7 +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE 12 +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE_QUALIFIER 13 +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH 18 +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_HEADER_LENGTH 8 + + +/* Define Storage Class read capacity command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_OPERATION 0 +#define UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_LUN 1 +#define UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_LBA 2 +#define UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_UFI 12 +#define UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_SBC 10 + + +/* Define Storage Class read capacity response constants. */ + +#define UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LAST_LBA 0 +#define UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_BLOCK_SIZE 4 +#define UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH 8 + +/* Define Storage Class read capacity response constants. */ + +#define UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_SIZE 0 +#define UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LAST_LBA 4 +#define UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_DESC_CODE 8 +#define UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_BLOCK_SIZE 8 +#define UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LENGTH 12 + +/* Define Storage Class test unit read command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_TEST_READY_OPERATION 0 +#define UX_SLAVE_CLASS_STORAGE_TEST_READY_LUN 1 +#define UX_SLAVE_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_UFI 12 +#define UX_SLAVE_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC 6 + + +/* Define Storage Class SCSI read command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_READ_OPERATION 0 +#define UX_SLAVE_CLASS_STORAGE_READ_LUN 1 +#define UX_SLAVE_CLASS_STORAGE_READ_LBA 2 +#define UX_SLAVE_CLASS_STORAGE_READ_TRANSFER_LENGTH_32 6 +#define UX_SLAVE_CLASS_STORAGE_READ_TRANSFER_LENGTH_16 7 +#define UX_SLAVE_CLASS_STORAGE_READ_COMMAND_LENGTH_UFI 12 +#define UX_SLAVE_CLASS_STORAGE_READ_COMMAND_LENGTH_SBC 10 + + +/* Define Storage Class SCSI write command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_WRITE_OPERATION 0 +#define UX_SLAVE_CLASS_STORAGE_WRITE_LUN 1 +#define UX_SLAVE_CLASS_STORAGE_WRITE_LBA 2 +#define UX_SLAVE_CLASS_STORAGE_WRITE_TRANSFER_LENGTH_32 6 +#define UX_SLAVE_CLASS_STORAGE_WRITE_TRANSFER_LENGTH_16 7 +#define UX_SLAVE_CLASS_STORAGE_WRITE_COMMAND_LENGTH_UFI 12 +#define UX_SLAVE_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC 10 + + +/* Define Storage Class SCSI sense key definition constants. */ + +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_NO_SENSE 0x0 +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_RECOVERED_ERROR 0x1 +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_NOT_READY 0x2 +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_MEDIUM_ERROR 0x3 +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_HARDWARE_ERROR 0x4 +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_ILLEGAL_REQUEST 0x5 +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_UNIT_ATTENTION 0x6 +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_DATA_PROTECT 0x7 +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_BLANK_CHECK 0x8 +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_ABORTED_COMMAND 0x0b +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_VOLUME_OVERFLOW 0x0d +#define UX_SLAVE_CLASS_STORAGE_SENSE_KEY_MISCOMPARE 0x0e + + +/* Define Storage Class SCSI sense key definition constants. */ + +#define UX_SLAVE_CLASS_STORAGE_REQUEST_CODE_MEDIA_PROTECTED 0x27 + +/* Define Storage Class SCSI GET CONFIGURATION command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_GET_CONFIGURATION_OPERATION 0 +#define UX_SLAVE_CLASS_STORAGE_GET_CONFIGURATION_RT 1 +#define UX_SLAVE_CLASS_STORAGE_GET_CONFIGURATION_STARTING_FEATURE 2 +#define UX_SLAVE_CLASS_STORAGE_GET_CONFIGURATION_ALLOCATION_LENGTH 7 +#define UX_SLAVE_CLASS_STORAGE_GET_CONFIGURATION_COMMAND_LENGTH_SBC 9 + +/* Define Storage Class SCSI ASC return codes. */ +#define UX_SLAVE_CLASS_STORAGE_ASC_KEY_INVALID_COMMAND 0x20 + +/* Define Storage Class CSW status. */ + +#define UX_SLAVE_CLASS_STORAGE_CSW_PASSED 0 +#define UX_SLAVE_CLASS_STORAGE_CSW_FAILED 1 +#define UX_SLAVE_CLASS_STORAGE_CSW_PHASE_ERROR 2 + +/* Define generic SCSI values. */ + +#define UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ERROR_CODE_VALUE 0x70 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_PAGE_CODE_STANDARD 0x00 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_PAGE_CODE_SERIAL 0x80 +#define UX_SLAVE_CLASS_STORAGE_INQUIRY_PERIPHERAL_TYPE 0x00 +#define UX_SLAVE_CLASS_STORAGE_RESET 0xff +#define UX_SLAVE_CLASS_STORAGE_GET_MAX_LUN 0xfe +#define UX_SLAVE_CLASS_STORAGE_MAX_LUN 0 +#define UX_SLAVE_CLASS_STORAGE_RESPONSE_LENGTH 64 + +/* Define Storage Class SCSI read disk information command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_READ_DISK_INFORMATION_OPERATION 0 +#define UX_SLAVE_CLASS_STORAGE_READ_DISK_INFORMATION_STATUS 2 +#define UX_SLAVE_CLASS_STORAGE_READ_DISK_INFORMATION_ALLOCATION_LENGTH 7 +#define UX_SLAVE_CLASS_STORAGE_READ_DISK_INFORMATION_LENGTH 10 + +/* Define Storage Class Feature Descriptor generic format. */ + +#define USBX_DEVICE_CLASS_STORAGE_FEATURE_DESCRIPTOR_FEATURE_CODE 0 +#define USBX_DEVICE_CLASS_STORAGE_FEATURE_DESCRIPTOR_FEATURE_PARAMETER 2 +#define USBX_DEVICE_CLASS_STORAGE_FEATURE_DESCRIPTOR_FEATURE_ADD_LENGTH 3 +#define USBX_DEVICE_CLASS_STORAGE_FEATURE_DESCRIPTOR_FEATURE_LENGTH 4 + + +/* Define Storage Class SCSI REPORT_KEY command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_OPERATION 0 +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ALLOCATION_LENGTH 8 +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_FORMAT 10 + +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_LENGTH 8 +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_PAYLOAD 6 +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_RESET_FIELD 4 +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_REGION_MASK 5 +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_RPC_SCHEME 6 + + +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_FORMAT_AGID 0 +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_FORMAT_CHALLENGE 1 +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_FORMAT_KEY2 2 +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_FORMAT_TITLE 4 +#define UX_SLAVE_CLASS_STORAGE_REPORT_KEY_FORMAT_RPC 8 + +/* Define Storage Class SCSI get event status notification command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_EVENT_NOTIFICATION_OPCODE 0 +#define UX_SLAVE_CLASS_STORAGE_EVENT_NOTIFICATION_IMMEDIATE 1 +#define UX_SLAVE_CLASS_STORAGE_EVENT_NOTIFICATION_CLASS_REQUEST 4 +#define UX_SLAVE_CLASS_STORAGE_EVENT_NOTIFICATION_ALLOCATION_LENGTH 7 +#define UX_SLAVE_CLASS_STORAGE_EVENT_NOTIFICATION_LENGTH 10 + +/* Define Storage Class SCSI read toc command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_READ_TOC_OPCODE 0 +#define UX_SLAVE_CLASS_STORAGE_READ_TOC_FORMAT 2 +#define UX_SLAVE_CLASS_STORAGE_READ_TOC_TRACK_NUMBER 6 +#define UX_SLAVE_CLASS_STORAGE_READ_TOC_ALLOCATION_LENGTH 7 + +/* Define Storage Class SCSI read DVD structure command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_READ_DVD_STRUCTURE_OPCODE 0 +#define UX_SLAVE_CLASS_STORAGE_READ_DVD_STRUCTURE_ADDRESS 2 +#define UX_SLAVE_CLASS_STORAGE_READ_DVD_STRUCTURE_FORMAT 7 +#define UX_SLAVE_CLASS_STORAGE_READ_DVD_STRUCTURE_ALLOCATION_LENGTH 8 + +#define UX_SLAVE_CLASS_STORAGE_READ_DVD_STRUCTURE_RESP_LENGTH 0 +#define UX_SLAVE_CLASS_STORAGE_READ_DVD_STRUCTURE_BOOK_TYPE 4 +#define UX_SLAVE_CLASS_STORAGE_READ_DVD_STRUCTURE_DS_MR 5 + + +/* Define Storage Class SCSI get performance command constants. */ + +#define UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAGE 1 +#define UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAGE_14 0x14 +#define UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAGE_0 0x00 +#define UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAYLOAD_LENGTH 4 +#define UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_RESPONSE_LENGTH 8 +#define UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAYLOAD 0x20000000 + +/* Define buffer length for IN/OUT pipes. This should match the size of the endpoint maximum buffer size. */ + +#define UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE UX_SLAVE_REQUEST_DATA_MAX_LENGTH + + +/* Define MMC2 CD-ROM / DVD-ROM bit fields */ + +#define UX_SLAVE_CLASS_STORAGE_MMC2_DISK_STATUS_EMPTY 0 +#define UX_SLAVE_CLASS_STORAGE_MMC2_DISK_STATUS_INCOMPLETE 1 +#define UX_SLAVE_CLASS_STORAGE_MMC2_DISK_STATUS_COMPLETE 2 +#define UX_SLAVE_CLASS_STORAGE_MMC2_DISK_STATUS_OTHERS 3 + +#define UX_SLAVE_CLASS_STORAGE_MMC2_LAT_SESSION_EMPTY 0 +#define UX_SLAVE_CLASS_STORAGE_MMC2_LAT_SESSION_INCOMPLETE 1 +#define UX_SLAVE_CLASS_STORAGE_MMC2_LAT_SESSION_COMPLETE 3 + + +/* Define Storage Class SCSI synchronize cache constants. */ + +#define UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS 1 +#define UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_LBA 2 +#define UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_NUMBER_OF_BLOCKS 7 + +#define UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS_IMMED 0x02 + + +/* Define MODE SENSE Page Codes. */ +#define UX_SLAVE_CLASS_STORAGE_MMC2_PAGE_CODE_CDROM 0x2a + +#define UX_SLAVE_CLASS_STORAGE_PAGE_CODE_CACHE 0x08 +#define UX_SLAVE_CLASS_STORAGE_PAGE_CODE_IEC 0x1C +#define UX_SLAVE_CLASS_STORAGE_PAGE_CODE_ALL 0x3F + + +/* Define Slave Storage Class LUN structure. */ + +typedef struct UX_SLAVE_CLASS_STORAGE_LUN_STRUCT +{ + ULONG ux_slave_class_storage_media_last_lba; + ULONG ux_slave_class_storage_media_block_length; + ULONG ux_slave_class_storage_media_type; + ULONG ux_slave_class_storage_media_removable_flag; + ULONG ux_slave_class_storage_media_read_only_flag; + ULONG ux_slave_class_storage_media_id; + ULONG ux_slave_class_storage_scsi_tag; + UCHAR ux_slave_class_storage_request_sense_key; + UCHAR ux_slave_class_storage_request_code; + UCHAR ux_slave_class_storage_request_code_qualifier; + ULONG ux_slave_class_storage_disk_status; + ULONG ux_slave_class_storage_last_session_state; + UINT (*ux_slave_class_storage_media_read)(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status); + UINT (*ux_slave_class_storage_media_write)(VOID *storage, ULONG lun, UCHAR *data_pointer, ULONG number_blocks, ULONG lba, ULONG *media_status); + UINT (*ux_slave_class_storage_media_flush)(VOID *storage, ULONG lun, ULONG number_blocks, ULONG lba, ULONG *media_status); + UINT (*ux_slave_class_storage_media_status)(VOID *storage, ULONG lun, ULONG media_id, ULONG *media_status); + UINT (*ux_slave_class_storage_media_notification)(VOID *storage, ULONG lun, ULONG media_id, ULONG notification_class, UCHAR **media_notification, ULONG *media_notification_length); +} UX_SLAVE_CLASS_STORAGE_LUN; + +/* Define Slave Storage Class structure. */ + +typedef struct UX_SLAVE_CLASS_STORAGE_STRUCT +{ + UX_SLAVE_INTERFACE *ux_slave_class_storage_interface; + ULONG ux_slave_class_storage_number_lun; + UX_SLAVE_CLASS_STORAGE_LUN ux_slave_class_storage_lun[UX_MAX_SLAVE_LUN]; + ULONG ux_slave_class_storage_phase_error; + VOID (*ux_slave_class_storage_instance_activate)(VOID *); + VOID (*ux_slave_class_storage_instance_deactivate)(VOID *); + UCHAR *ux_slave_class_storage_vendor_id; + UCHAR *ux_slave_class_storage_product_id; + UCHAR *ux_slave_class_storage_product_rev; + UCHAR *ux_slave_class_storage_product_serial; + +} UX_SLAVE_CLASS_STORAGE; + +/* Define Slave Storage Class Calling Parameter structure */ + +typedef struct UX_SLAVE_CLASS_STORAGE_PARAMETER_STRUCT +{ + VOID (*ux_slave_class_storage_instance_activate)(VOID *); + VOID (*ux_slave_class_storage_instance_deactivate)(VOID *); + ULONG ux_slave_class_storage_parameter_number_lun; + UX_SLAVE_CLASS_STORAGE_LUN ux_slave_class_storage_parameter_lun[UX_MAX_SLAVE_LUN]; + UCHAR *ux_slave_class_storage_parameter_vendor_id; + UCHAR *ux_slave_class_storage_parameter_product_id; + UCHAR *ux_slave_class_storage_parameter_product_rev; + UCHAR *ux_slave_class_storage_parameter_product_serial; + +} UX_SLAVE_CLASS_STORAGE_PARAMETER; + +/* Define Device Storage Class prototypes. */ + +UINT _ux_device_class_storage_initialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_storage_uninitialize(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_storage_activate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_storage_control_request(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_storage_csw_send(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, UCHAR csw_status); +UINT _ux_device_class_storage_deactivate(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_storage_entry(UX_SLAVE_CLASS_COMMAND *command); +UINT _ux_device_class_storage_format(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_inquiry(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_mode_select(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_mode_sense(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_prevent_allow_media_removal(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb); +UINT _ux_device_class_storage_read(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb, UCHAR scsi_command); +UINT _ux_device_class_storage_read_capacity(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_read_format_capacity(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_read_toc(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb); +UINT _ux_device_class_storage_request_sense(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_start_stop(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_test_ready(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +VOID _ux_device_class_storage_thread(ULONG storage_instance); +UINT _ux_device_class_storage_verify(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_write(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb, UCHAR scsi_command); +UINT _ux_device_class_storage_synchronize_cache(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb, UCHAR scsi_command); +UINT _ux_device_class_storage_read_disk_information(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); + +UINT _ux_device_class_storage_get_configuration(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_get_status_notification(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); +UINT _ux_device_class_storage_report_key(UX_SLAVE_CLASS_STORAGE *storage, + ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, + UCHAR *cbwcb); + +UINT _ux_device_class_storage_get_performance(UX_SLAVE_CLASS_STORAGE *storage, + ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, + UCHAR *cbwcb); +UINT _ux_device_class_storage_read_dvd_structure(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb); + +/* Define Device Storage Class API prototypes. */ + +#define ux_device_class_storage_entry _ux_device_class_storage_entry + +#endif diff --git a/common/usbx_device_classes/src/ux_device_class_audio10_control_process.c b/common/usbx_device_classes/src/ux_device_class_audio10_control_process.c new file mode 100644 index 0000000..d742db1 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio10_control_process.c @@ -0,0 +1,237 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_class_audio10.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio10_control_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* audio Address of audio class */ +/* instance */ +/* transfer Address of transfer request */ +/* instance */ +/* group Request process data */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_short_get Get 2-byte value from buffer */ +/* _ux_utility_short_put Put 2-byte value to buffer */ +/* _ux_device_stack_transfer_request Issue a transfer request */ +/* _ux_device_stack_endpoint_stall Endpoint stall */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio10_control_process(UX_DEVICE_CLASS_AUDIO *audio, + UX_SLAVE_TRANSFER *transfer, UX_DEVICE_CLASS_AUDIO10_CONTROL_GROUP *group) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_DEVICE_CLASS_AUDIO10_CONTROL *control; +UCHAR request; +UCHAR unit_id; +UCHAR control_selector; +UCHAR channel_number; +ULONG request_length; +ULONG i; + + + /* Get instances. */ + endpoint = &audio -> ux_device_class_audio_device -> ux_slave_device_control_endpoint; + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Extract all necessary fields of the request. */ + request = *(transfer -> ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_REQUEST); + unit_id = *(transfer -> ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_ENEITY_ID); + control_selector = *(transfer -> ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_CONTROL_SELECTOR); + channel_number = *(transfer -> ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_CHANNEL_NUMBER); + request_length = _ux_utility_short_get(transfer -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH); + + /* Process controls one by one. */ + for (i = 0; i < group -> ux_device_class_audio10_control_group_controls_nb; i ++) + { + control = &group -> ux_device_class_audio10_control_group_controls[i]; + + /* Reset change map. */ + control -> ux_device_class_audio10_control_changed = 0; + + /* We handle feature unit requests. */ + if (unit_id == control -> ux_device_class_audio10_control_fu_id) + { + + /* Handle the request. */ + switch(request) + { + case UX_DEVICE_CLASS_AUDIO10_SET_CUR: + + /* We only support master channel, so channel number must be 0 or 0xFF. */ + if (channel_number != 0 && channel_number != 0xFF) + break; + + /* Set request. */ + switch(control_selector) + { + case UX_DEVICE_CLASS_AUDIO10_FU_MUTE_CONTROL: + + if (transfer -> ux_slave_transfer_request_actual_length < 1) + + /* No change applied. */ + break; + + if (control -> ux_device_class_audio10_control_mute[0] != transfer -> ux_slave_transfer_request_data_pointer[0]) + { + control -> ux_device_class_audio10_control_changed = UX_DEVICE_CLASS_AUDIO10_CONTROL_MUTE_CHANGED; + control -> ux_device_class_audio10_control_mute[0] = transfer -> ux_slave_transfer_request_data_pointer[0]; + + } + + /* Done success. */ + return(UX_SUCCESS); + + case UX_DEVICE_CLASS_AUDIO10_FU_VOLUME_CONTROL: + + if (transfer -> ux_slave_transfer_request_actual_length < 2) + + /* No change applied. */ + break; + + if (control -> ux_device_class_audio10_control_volume[0] != (SHORT)_ux_utility_short_get(transfer -> ux_slave_transfer_request_data_pointer)) + { + control -> ux_device_class_audio10_control_changed = UX_DEVICE_CLASS_AUDIO10_CONTROL_VOLUME_CHANGED; + control -> ux_device_class_audio10_control_volume[0] = (SHORT)_ux_utility_short_get(transfer -> ux_slave_transfer_request_data_pointer); + } + + /* Done success. */ + return(UX_SUCCESS); + + + default: + + /* No change applied. */ + break; + } + + /* Request or parameter problem. */ + break; + + case UX_DEVICE_CLASS_AUDIO10_GET_MIN: + case UX_DEVICE_CLASS_AUDIO10_GET_MAX: + case UX_DEVICE_CLASS_AUDIO10_GET_RES: + case UX_DEVICE_CLASS_AUDIO10_GET_CUR: + + /* We only support master channel, so channel number must be 0 or 0xFF. */ + if (channel_number != 0 && channel_number != 0xFF) + break; + + /* Get request. */ + switch(control_selector) + { + case UX_DEVICE_CLASS_AUDIO10_FU_MUTE_CONTROL: + + /* We only support _CUR. */ + if (request != UX_DEVICE_CLASS_AUDIO10_GET_CUR) + break; + + /* Not enough buffer for data. */ + if (request_length < 1) + break; + + /* Send mute status. */ + transfer -> ux_slave_transfer_request_data_pointer[0] = (UCHAR)control -> ux_device_class_audio10_control_mute[0]; + _ux_device_stack_transfer_request(transfer, 1, request_length); + + /* Done success. */ + return(UX_SUCCESS); + + case UX_DEVICE_CLASS_AUDIO10_FU_VOLUME_CONTROL: + + /* Not enough buffer for data. */ + if (request_length < 2) + break; + + /* Send volume value. */ + _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer, (USHORT) + (request == UX_DEVICE_CLASS_AUDIO10_GET_MIN ? control -> ux_device_class_audio10_control_volume_min[0] : + (request == UX_DEVICE_CLASS_AUDIO10_GET_MAX ? control -> ux_device_class_audio10_control_volume_max[0] : + (request == UX_DEVICE_CLASS_AUDIO10_GET_RES ? 0x0001 : + control -> ux_device_class_audio10_control_volume[0])))); + _ux_device_stack_transfer_request(transfer, 2, request_length); + + /* Done success. */ + return(UX_SUCCESS); + + default: + break; + } + + default: + break; + } + + /* We are here when there is error, break the loop. */ + break; + } + + /* Now try next. */ + } + + + /* Request or parameter not supported. */ + _ux_device_stack_endpoint_stall(endpoint); + + /* Done error. */ + return(UX_ERROR); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio20_control_process.c b/common/usbx_device_classes/src/ux_device_class_audio20_control_process.c new file mode 100644 index 0000000..9474f87 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio20_control_process.c @@ -0,0 +1,295 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_class_audio20.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_control_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* audio Address of audio class */ +/* instance */ +/* transfer Address of transfer request */ +/* instance */ +/* group Request process data */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_short_get Get 2-byte value from buffer */ +/* _ux_utility_short_put Put 2-byte value to buffer */ +/* _ux_utility_long_put Put 4-byte value to buffer */ +/* _ux_device_stack_transfer_request Issue a transfer request */ +/* _ux_device_stack_endpoint_stall Endpoint stall */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio20_control_process(UX_DEVICE_CLASS_AUDIO *audio, + UX_SLAVE_TRANSFER *transfer, + UX_DEVICE_CLASS_AUDIO20_CONTROL_GROUP *group) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_DEVICE_CLASS_AUDIO20_CONTROL *control; +UCHAR request; +UCHAR request_type; +UCHAR unit_id; +UCHAR control_selector; +UCHAR channel_number; +ULONG request_length; +ULONG i; + + + /* Get instances. */ + endpoint = &audio -> ux_device_class_audio_device -> ux_slave_device_control_endpoint; + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Extract all necessary fields of the request. */ + request = *(transfer -> ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_REQUEST); + request_type = *(transfer -> ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_REQUEST_TYPE); + unit_id = *(transfer -> ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_ENEITY_ID); + control_selector = *(transfer -> ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_CONTROL_SELECTOR); + channel_number = *(transfer -> ux_slave_transfer_request_setup + UX_DEVICE_CLASS_AUDIO_REQUEST_CHANNEL_NUMBER); + request_length = _ux_utility_short_get(transfer -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH); + + for (i = 0; i < group -> ux_device_class_audio20_control_group_controls_nb; i ++) + { + control = &group -> ux_device_class_audio20_control_group_controls[i]; + + /* Reset change map. */ + control -> ux_device_class_audio20_control_changed = 0; + + /* Is this request a clock unit request? */ + if (unit_id == control -> ux_device_class_audio20_control_cs_id) + { + + /* Clock Source request. + * We only support Sampling Frequency Control here. + * The Sampling Frequency Control must support the CUR and RANGE(MIN, MAX, RES) attributes. + */ + + /* We just support sampling frequency control, GET request. */ + if ((request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN && + (control_selector == UX_DEVICE_CLASS_AUDIO20_CS_SAM_FREQ_CONTROL)) + { + + switch(request) + { + case UX_DEVICE_CLASS_AUDIO20_CUR: + + /* Check request parameter. */ + if (request_length < 4) + break; + + /* Send sampling frequency. + * We only support one here (from extension data). + */ + _ux_utility_long_put(transfer -> ux_slave_transfer_request_data_pointer, control -> ux_device_class_audio20_control_sampling_frequency); + _ux_device_stack_transfer_request(transfer, 4, request_length); + return(UX_SUCCESS); + + case UX_DEVICE_CLASS_AUDIO20_RANGE: + + /* Check request parameter. */ + if (request_length < 2) + break; + + /* Send range parameters. + * We only support one here (from extension data). + * wNumSubRanges : 1 + * dMIN : sampling frequency + * dMAX : sampling frequency + * dRES : 1 + */ + _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer, 1); + _ux_utility_long_put(transfer -> ux_slave_transfer_request_data_pointer + 2, control -> ux_device_class_audio20_control_sampling_frequency); + _ux_utility_long_put(transfer -> ux_slave_transfer_request_data_pointer + 6, control -> ux_device_class_audio20_control_sampling_frequency); + _ux_utility_long_put(transfer -> ux_slave_transfer_request_data_pointer + 10, 0); + _ux_device_stack_transfer_request(transfer, 14, request_length); + return(UX_SUCCESS); + + default: + break; + } + } + + /* We are here when there is error on handling CU, break. */ + break; + } /* if (unit_id == control -> ux_device_class_audio20_control_cs_id) */ + + /* Is this request a feature unit request? */ + if (unit_id == control -> ux_device_class_audio20_control_fu_id) + { + + /* Feature Unit request. + * We only support master channel, mute and volume here. + * Mute have only the CUR. + * Volume must support CUR and RANGE(MIN,MAX,RES). + */ + + /* Check control selector. */ + switch(control_selector) + { + case UX_DEVICE_CLASS_AUDIO20_FU_MUTE_CONTROL: + + /* Check channel number, we support master channel only. */ + if (channel_number != 0) + break; + + /* Handle request. */ + switch(request) + { + case UX_DEVICE_CLASS_AUDIO20_CUR: + + + /* Check buffer size. */ + if (request_length < 1) + break; + + /* GET_CUR. */ + if ((request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + { + + /* Send mute. */ + transfer -> ux_slave_transfer_request_data_pointer[0] = (UCHAR)control -> ux_device_class_audio20_control_mute[0]; + _ux_device_stack_transfer_request(transfer, 1, request_length); + } + else if (control -> ux_device_class_audio20_control_mute[0] != transfer -> ux_slave_transfer_request_data_pointer[0]) + { + + /* Update mute. */ + control -> ux_device_class_audio20_control_changed = UX_DEVICE_CLASS_AUDIO20_CONTROL_MUTE_CHANGED; + control -> ux_device_class_audio20_control_mute[0] = transfer -> ux_slave_transfer_request_data_pointer[0]; + } + /* Done success. */ + return(UX_SUCCESS); + + default: + break; + } + break; + + case UX_DEVICE_CLASS_AUDIO20_FU_VOLUME_CONTROL: + + /* Check channel number, we support master channel only. */ + if (channel_number != 0) + break; + + /* Handle request. */ + switch(request) + { + case UX_DEVICE_CLASS_AUDIO20_CUR: + + /* Check buffer size. */ + if (request_length < 2) + break; + + /* GET_CUR. */ + if ((request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + { + + /* Send volume. */ + _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer, (USHORT)control -> ux_device_class_audio20_control_volume[0]); + _ux_device_stack_transfer_request(transfer, 2, request_length); + } + else if (control -> ux_device_class_audio20_control_volume[0] != (SHORT)_ux_utility_short_get(transfer -> ux_slave_transfer_request_data_pointer)) + { + + /* Update volume. */ + control -> ux_device_class_audio20_control_changed = UX_DEVICE_CLASS_AUDIO20_CONTROL_VOLUME_CHANGED; + control -> ux_device_class_audio20_control_volume[0] = (SHORT)_ux_utility_short_get(transfer -> ux_slave_transfer_request_data_pointer); + } + + /* Done success. */ + return(UX_SUCCESS); + + case UX_DEVICE_CLASS_AUDIO20_RANGE: + + /* Only support GET_CUR. */ + if ((request_type & UX_REQUEST_DIRECTION) != UX_REQUEST_IN) + break; + + /* Check buffer size. */ + if (request_length < 8) + break; + + /* Send wNumSubRanges,wMIN,wMAX,wRES. */ + _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer + 0, 1); + _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer + 2, (USHORT)control -> ux_device_class_audio20_control_volume_min[0]); + _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer + 4, (USHORT)control -> ux_device_class_audio20_control_volume_max[0]); + _ux_utility_short_put(transfer -> ux_slave_transfer_request_data_pointer + 6, 1); + _ux_device_stack_transfer_request(transfer, 8, request_length); + + /* Done success. */ + return(UX_SUCCESS); + + default: + break; + } + break; + + default: + break; + } + + /* We are here when there is error on handling FU, break. */ + break; + } /* if (unit_id == control -> ux_device_class_audio20_control_fu_id) */ + } + + /* Request or parameter not supported. */ + _ux_device_stack_endpoint_stall(endpoint); + return(UX_ERROR); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_activate.c b/common/usbx_device_classes/src/ux_device_class_audio_activate.c new file mode 100644 index 0000000..24e1ca1 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_activate.c @@ -0,0 +1,166 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB Audio device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to audio command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler System error trap */ +/* */ +/* CALLED BY */ +/* */ +/* Device Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_activate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_DEVICE *device; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_INTERFACE *control_interface; +UX_SLAVE_INTERFACE *stream_interface; +UX_DEVICE_CLASS_AUDIO *audio; +UX_DEVICE_CLASS_AUDIO_STREAM *stream; +UX_SLAVE_CLASS *class; +ULONG stream_index; + + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + audio = (UX_DEVICE_CLASS_AUDIO *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Get the device instance. */ + device = &_ux_system_slave -> ux_system_slave_device; + audio -> ux_device_class_audio_device = device; + + /* We only support audio interface here. */ + if (interface -> ux_slave_interface_descriptor.bInterfaceClass != UX_DEVICE_CLASS_AUDIO_CLASS) + return(UX_NO_CLASS_MATCH); + + /* It's control interface? */ + if (interface -> ux_slave_interface_descriptor.bInterfaceSubClass == UX_DEVICE_CLASS_AUDIO_SUBCLASS_CONTROL) + { + + /* Store the interface in the class instance. */ + audio -> ux_device_class_audio_interface = interface; + + /* Store the class instance into the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)audio; + } + else + { + + /* It's streaming interface. */ + stream_interface = interface; + + /* Separate driver for each interface (IAD not used)? */ + if (audio -> ux_device_class_audio_interface == UX_NULL) + { + + /* Always use just 1 stream for 1 interface. */ + stream_index = 0; + } + + /* Re-use the same driver (IAD used)? */ + else + { + + /* Re-use saved control interface. */ + control_interface = audio -> ux_device_class_audio_interface; + + /* Calculate stream index. */ + stream_index = stream_interface -> ux_slave_interface_descriptor.bInterfaceNumber; + stream_index -= control_interface -> ux_slave_interface_descriptor.bInterfaceNumber; + stream_index --; + + } + + /* Sanity check. */ + if (stream_index >= audio -> ux_device_class_audio_streams_nb) + { + + /* Error trap! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + return(UX_MEMORY_INSUFFICIENT); + } + + /* Locate stream based on interface number. */ + stream = &audio -> ux_device_class_audio_streams[stream_index]; + + /* Store the interface for the stream. */ + stream -> ux_device_class_audio_stream_interface = stream_interface; + + /* Store the class instance into the interface. */ + stream_interface -> ux_slave_interface_class_instance = (VOID *)audio; + } + + /* If there is a activate function call it. */ + if (audio -> ux_device_class_audio_callbacks.ux_slave_class_audio_instance_activate != UX_NULL) + { + + /* Invoke the application. */ + audio -> ux_device_class_audio_callbacks.ux_slave_class_audio_instance_activate(audio); + } + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_change.c b/common/usbx_device_classes/src/ux_device_class_audio_change.c new file mode 100644 index 0000000..41051c9 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_change.c @@ -0,0 +1,192 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_change PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function changes the interface of the Audio device */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to audio command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler System error trap */ +/* */ +/* CALLED BY */ +/* */ +/* Device Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_change(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_DEVICE_CLASS_AUDIO *audio; +UX_DEVICE_CLASS_AUDIO_STREAM *stream; +UX_SLAVE_CLASS *class; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_ENDPOINT *endpoint; +UCHAR *frame_buffer; +ULONG stream_index; + + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + audio = (UX_DEVICE_CLASS_AUDIO *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Get the interface number (base 0). */ + if (audio -> ux_device_class_audio_interface) + { + + /* If IAD used, calculate stream index based on interface number. */ + stream_index = interface -> ux_slave_interface_descriptor.bInterfaceNumber; + stream_index -= audio -> ux_device_class_audio_interface -> ux_slave_interface_descriptor.bInterfaceNumber; + stream_index --; + } + else + + /* One stream for one driver! */ + stream_index = 0; + + /* Get the stream instance. */ + stream = &audio -> ux_device_class_audio_streams[stream_index]; + + /* Update the interface. */ + stream -> ux_device_class_audio_stream_interface = interface; + + /* If the interface to mount has a non zero alternate setting, the class is really active with + the endpoints active. If the interface reverts to alternate setting 0, it needs to have + the pending transactions terminated. */ + if (interface -> ux_slave_interface_descriptor.bAlternateSetting != 0) + { + + /* Locate the endpoints. ISO IN/OUT for Streaming Interface. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Parse all endpoints. */ + stream -> ux_device_class_audio_stream_endpoint = UX_NULL; + while (endpoint != UX_NULL) + { + + /* Check the endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & + (UX_DEVICE_CLASS_AUDIO_EP_TRANSFER_TYPE_MASK | UX_DEVICE_CLASS_AUDIO_EP_USAGE_TYPE_MASK)) == UX_ISOCHRONOUS_ENDPOINT) + { + + /* We found the endpoint, check its size. */ + if (endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize > stream -> ux_device_class_audio_stream_frame_buffer_size - 8) + { + + /* Error trap! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + + /* Frame buffer too small for endpoints. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Save it. */ + stream -> ux_device_class_audio_stream_endpoint = endpoint; + break; + } + + /* Next endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* Now check if all endpoints have been found. */ + if (stream -> ux_device_class_audio_stream_endpoint == UX_NULL) + { + + /* Error trap! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* Not all endpoints have been found. Major error, do not proceed. */ + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Now reset frame buffers. */ + frame_buffer = stream -> ux_device_class_audio_stream_buffer; + while(frame_buffer < stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + { + + /* Reset header information. */ + *((ULONG *) frame_buffer ) = 0; + *((ULONG *)(frame_buffer + 4)) = 0; + + /* Next. */ + frame_buffer += stream -> ux_device_class_audio_stream_frame_buffer_size; + } + stream -> ux_device_class_audio_stream_transfer_pos = stream -> ux_device_class_audio_stream_access_pos; + } + else + { + + /* There is no data endpoint. */ + stream -> ux_device_class_audio_stream_endpoint = UX_NULL; + + /* In this case, we are reverting to the Alternate Setting 0. We need to terminate the pending transactions. */ + /* Endpoints actually aborted and destroyed before change command. */ + /* + _ux_device_stack_transfer_all_request_abort(stream -> ux_device_class_audio_stream_endpoint, UX_TRANSFER_APPLICATION_RESET); + */ + } + + /* Invoke stream change callback. */ + if (stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_change) + stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_change(stream, interface -> ux_slave_interface_descriptor.bAlternateSetting); + + /* Return completion status. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_control_request.c b/common/usbx_device_classes/src/ux_device_class_audio_control_request.c new file mode 100644 index 0000000..da96385 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_control_request.c @@ -0,0 +1,101 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_control_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_endpoint_stall Endpoint stall */ +/* */ +/* CALLED BY */ +/* */ +/* Device Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_control_request(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +UX_SLAVE_CLASS *class; +UX_DEVICE_CLASS_AUDIO *audio; + + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the audio instance from this class container. */ + audio = (UX_DEVICE_CLASS_AUDIO *) class -> ux_slave_class_instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the pointer to the transfer request associated with the control endpoint. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Invoke callback. */ + if (audio -> ux_device_class_audio_callbacks.ux_device_class_audio_control_process != UX_NULL) + { + + /* Handled by callback. */ + return audio -> ux_device_class_audio_callbacks.ux_device_class_audio_control_process(audio, transfer_request); + } + + /* Not handled. */ + return(UX_ERROR); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_deactivate.c b/common/usbx_device_classes/src/ux_device_class_audio_deactivate.c new file mode 100644 index 0000000..6e1eaf7 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_deactivate.c @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivate an instance of the audio class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_all_request_abort */ +/* Abort all transfers */ +/* */ +/* CALLED BY */ +/* */ +/* Device Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_deactivate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_DEVICE_CLASS_AUDIO *audio; +UX_DEVICE_CLASS_AUDIO_STREAM *stream; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_CLASS *class; +UINT i; + + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + audio = (UX_DEVICE_CLASS_AUDIO *) class -> ux_slave_class_instance; + + /* Stop pending streams. */ + stream = audio -> ux_device_class_audio_streams; + for (i = 0; i < audio -> ux_device_class_audio_streams_nb; i ++) + { + + /* Locate the endpoint. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + + /* Terminate the transactions pending on the endpoint. */ + if (endpoint) + _ux_device_stack_transfer_all_request_abort(endpoint, UX_TRANSFER_BUS_RESET); + + /* Free the stream. */ + stream -> ux_device_class_audio_stream_endpoint = UX_NULL; + stream -> ux_device_class_audio_stream_interface = UX_NULL; + + stream ++; + } + + /* Free the control. */ + audio -> ux_device_class_audio_interface = UX_NULL; + + /* If there is a deactivate function call it. */ + if (audio -> ux_device_class_audio_callbacks.ux_slave_class_audio_instance_deactivate != UX_NULL) + + /* Invoke the application. */ + audio -> ux_device_class_audio_callbacks.ux_slave_class_audio_instance_deactivate(audio); + + /* Return completion status. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_entry.c b/common/usbx_device_classes/src/ux_device_class_audio_entry.c new file mode 100644 index 0000000..ccbd65d --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_entry.c @@ -0,0 +1,158 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_class_device_audio_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the audio class. It */ +/* will be called by the device stack enumeration module when the */ +/* host has sent a SET_CONFIGURATION command and the audio interface */ +/* needs to be mounted. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_audio_initialize Initialize audio class */ +/* _ux_device_class_audio_uninitialize Uninitialize audio class */ +/* _ux_device_class_audio_activate Activate audio class */ +/* _ux_device_class_audio_change Change audio interface */ +/* _ux_device_class_audio_deactivate Deactivate audio class */ +/* _ux_device_class_audio_control_request Request control */ +/* */ +/* CALLED BY */ +/* */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_entry(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_slave_class_command_request) + { + + case UX_SLAVE_CLASS_COMMAND_INITIALIZE: + + /* Call the init function of the Audio class. */ + status = _ux_device_class_audio_initialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_UNINITIALIZE: + + /* Call the init function of the Audio class. */ + status = _ux_device_class_audio_uninitialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_QUERY: + + /* Check the CLASS definition in the interface descriptor. */ + if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_AUDIO_CLASS) + { + if (command -> ux_slave_class_command_subclass == UX_DEVICE_CLASS_AUDIO_SUBCLASS_CONTROL) + return(UX_SUCCESS); + if (command -> ux_slave_class_command_subclass == UX_DEVICE_CLASS_AUDIO_SUBCLASS_AUDIOSTREAMING) + return(UX_SUCCESS); + } + return(UX_NO_CLASS_MATCH); + + case UX_SLAVE_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the host has sent a SET_CONFIGURATION command + and this interface has to be mounted. Both Bulk endpoints have to be mounted + and the audio thread needs to be activated. */ + status = _ux_device_class_audio_activate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_CHANGE: + + /* The change command is used when the host has sent a SET_INTERFACE command + to go from Alternate Setting 0 to 1 or revert to the default mode. */ + status = _ux_device_class_audio_change(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted. + The device endpoints have to be dismounted and the audio thread canceled. */ + status = _ux_device_class_audio_deactivate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_REQUEST: + + /* The request command is used when the host sends a command on the control endpoint. */ + _ux_device_class_audio_control_request(command); + + /* Return the completion status. */ + return(UX_SUCCESS); + + default: + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_frame_write.c b/common/usbx_device_classes/src/ux_device_class_audio_frame_write.c new file mode 100644 index 0000000..8042209 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_frame_write.c @@ -0,0 +1,127 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_frame_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes frame to the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* frame Pointer to buffer to save */ +/* frame data */ +/* length Frame length in bytes */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_copy Copy data */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_frame_write(UX_DEVICE_CLASS_AUDIO_STREAM *stream, UCHAR *frame, ULONG length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UCHAR *next_frame_buffer; +ULONG frame_buffer_size; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK (IN). */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Check frame length. */ + frame_buffer_size = stream -> ux_device_class_audio_stream_frame_buffer_size; + if (frame_buffer_size < length) + return(UX_ERROR); + + /* Check overflow!! */ + if (stream -> ux_device_class_audio_stream_access_pos == stream -> ux_device_class_audio_stream_transfer_pos && + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length != 0) + return(UX_BUFFER_OVERFLOW); + + /* Calculate next frame buffer. */ + next_frame_buffer = (UCHAR *)stream -> ux_device_class_audio_stream_access_pos; + next_frame_buffer += frame_buffer_size; + if (next_frame_buffer >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_frame_buffer = stream -> ux_device_class_audio_stream_buffer; + + /* Copy frame. */ + _ux_utility_memory_copy(stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_data, frame, length); + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length = length; + + /* Move frame position. */ + stream -> ux_device_class_audio_stream_access_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_frame_buffer; + + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_initialize.c b/common/usbx_device_classes/src/ux_device_class_audio_initialize.c new file mode 100644 index 0000000..a085e28 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_initialize.c @@ -0,0 +1,238 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB Audio device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to audio command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_thread_create Create thread to use */ +/* _ux_utility_thread_delete Delete thread */ +/* */ +/* CALLED BY */ +/* */ +/* Device Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_initialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status = UX_SUCCESS; +UX_DEVICE_CLASS_AUDIO *audio; +UX_DEVICE_CLASS_AUDIO_PARAMETER *audio_parameter; +UX_DEVICE_CLASS_AUDIO_STREAM *stream; +UX_DEVICE_CLASS_AUDIO_STREAM_PARAMETER *stream_parameter; +UX_SLAVE_CLASS *class; +ULONG memory_size; +ULONG streams_size; +ULONG i; + + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the pointer to the application parameters for the audio class. */ + audio_parameter = (UX_DEVICE_CLASS_AUDIO_PARAMETER *)command -> ux_slave_class_command_parameter; + + /* Create an instance of the device audio class, with additional streams and controls instances. */ + memory_size = sizeof(UX_DEVICE_CLASS_AUDIO); + + /* Put 0 to default result. */ + streams_size = 0; + + /* Confirm there is no overflow on multiply. */ + UX_UTILITY_MULC_SAFE(audio_parameter -> ux_device_class_audio_parameter_streams_nb, (ULONG)sizeof(UX_DEVICE_CLASS_AUDIO_STREAM), streams_size, status); + if (status != UX_SUCCESS) + return(status); + + /* Confirm there is no overflow on add. */ + UX_UTILITY_ADD_SAFE(memory_size, streams_size, memory_size, status); + if (status != UX_SUCCESS) + return(status); + + /* Create buffer for audio and controls. */ + audio = (UX_DEVICE_CLASS_AUDIO *)_ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size); + + /* Check for successful allocation. */ + if (audio == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save streams. */ + if (streams_size) + { + audio -> ux_device_class_audio_streams = (UX_DEVICE_CLASS_AUDIO_STREAM *)((UCHAR *)audio + sizeof(UX_DEVICE_CLASS_AUDIO)); + audio -> ux_device_class_audio_streams_nb = audio_parameter -> ux_device_class_audio_parameter_streams_nb; + } + + /* Allocate resources for streams. */ + stream = audio -> ux_device_class_audio_streams; + stream_parameter = audio_parameter -> ux_device_class_audio_parameter_streams; + for (i = 0; i < audio -> ux_device_class_audio_streams_nb; i ++) + { + + /* Create memory block based on max frame buffer size and max number of frames buffered. + Each frame require some additional header memory (8 bytes). */ + stream -> ux_device_class_audio_stream_frame_buffer_size = stream_parameter -> ux_device_class_audio_stream_parameter_max_frame_buffer_size; + + if (UX_OVERFLOW_CHECK_ADD_USHORT(stream -> ux_device_class_audio_stream_frame_buffer_size, 8)) + { + status = UX_ERROR; + break; + } + stream -> ux_device_class_audio_stream_frame_buffer_size += 8; + + if (UX_OVERFLOW_CHECK_MULV_ULONG(stream -> ux_device_class_audio_stream_frame_buffer_size, + stream_parameter -> ux_device_class_audio_stream_parameter_max_frame_buffer_nb)) + { + status = UX_ERROR; + break; + } + memory_size = stream -> ux_device_class_audio_stream_frame_buffer_size * + stream_parameter -> ux_device_class_audio_stream_parameter_max_frame_buffer_nb; + + /* Create block of buffer buffer is cache safe for USB transfer. */ + stream -> ux_device_class_audio_stream_buffer = (UCHAR *)_ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size); + + /* Check for successful allocation. */ + if (stream -> ux_device_class_audio_stream_buffer == UX_NULL) + { + status = UX_MEMORY_INSUFFICIENT; + break; + } + + stream -> ux_device_class_audio_stream_buffer_size = memory_size; + stream -> ux_device_class_audio_stream_transfer_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)stream -> ux_device_class_audio_stream_buffer; + stream -> ux_device_class_audio_stream_access_pos = stream -> ux_device_class_audio_stream_transfer_pos; + + /* Create memory block for streaming thread stack in addition. */ + if (stream_parameter -> ux_device_class_audio_stream_parameter_thread_stack_size == 0) + memory_size = UX_THREAD_STACK_SIZE; + else + memory_size = stream_parameter -> ux_device_class_audio_stream_parameter_thread_stack_size; + stream -> ux_device_class_audio_stream_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, memory_size); + + /* Check for successful allocation. */ + if (stream -> ux_device_class_audio_stream_thread_stack == UX_NULL) + { + status = UX_MEMORY_INSUFFICIENT; + break; + } + + /* Create streaming thread. */ + status = _ux_utility_thread_create(&stream -> ux_device_class_audio_stream_thread , "ux_device_class_audio_stream_thread", + stream_parameter -> ux_device_class_audio_stream_parameter_thread_entry, + (ULONG)(ALIGN_TYPE)stream, (VOID *) stream -> ux_device_class_audio_stream_thread_stack, + memory_size, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_DONT_START); + + /* Check for successful allocation. */ + if (status != UX_SUCCESS) + break; + + UX_THREAD_EXTENSION_PTR_SET(&(stream -> ux_device_class_audio_stream_thread), stream) + + /* Save callbacks. */ + _ux_utility_memory_copy(&stream -> ux_device_class_audio_stream_callbacks, + &stream_parameter -> ux_device_class_audio_stream_parameter_callbacks, + sizeof(UX_DEVICE_CLASS_AUDIO_STREAM_CALLBACKS)); + + /* Save audio instance. */ + stream -> ux_device_class_audio_stream_audio = audio; + + stream ++; + stream_parameter ++; + } + + /* Check for successful creation. */ + if (status == UX_SUCCESS) + { + + /* Save the address of the Audio instance inside the Audio container. */ + class -> ux_slave_class_instance = (VOID *) audio; + + /* Link to class instance. */ + audio -> ux_device_class_audio_class = class; + + /* Save callbacks. */ + _ux_utility_memory_copy(&audio -> ux_device_class_audio_callbacks, + &audio_parameter -> ux_device_class_audio_parameter_callbacks, + sizeof(UX_DEVICE_CLASS_AUDIO_CALLBACKS)); + + /* Return completion status. */ + return(UX_SUCCESS); + } + + /* Error trap! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + + /* Free allocated resources. */ + stream = audio -> ux_device_class_audio_streams; + for (i = 0; i < audio -> ux_device_class_audio_streams_nb; i ++) + { + if (stream -> ux_device_class_audio_stream_thread.tx_thread_id) + _ux_utility_thread_delete(&stream -> ux_device_class_audio_stream_thread); + if (stream -> ux_device_class_audio_stream_thread_stack) + _ux_utility_memory_free(stream -> ux_device_class_audio_stream_thread_stack); + if (stream -> ux_device_class_audio_stream_buffer) + _ux_utility_memory_free(stream -> ux_device_class_audio_stream_buffer); + stream ++; + } + _ux_utility_memory_free(audio); + + return(status); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_ioctl.c b/common/usbx_device_classes/src/ux_device_class_audio_ioctl.c new file mode 100644 index 0000000..99797de --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_ioctl.c @@ -0,0 +1,106 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_ioctl PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs certain functions on the audio instance */ +/* */ +/* INPUT */ +/* */ +/* audio Address of audio class */ +/* instance */ +/* ioctl_function IOCTL function code */ +/* parameter Parameter for function */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_ioctl(UX_DEVICE_CLASS_AUDIO *audio, ULONG ioctl_function, + VOID *parameter) +{ + +UINT status; +VOID **pptr_parameter; + + + /* Let's be optimist ! */ + status = UX_SUCCESS; + + /* The command request will tell us what we need to do here. */ + switch (ioctl_function) + { + + case UX_DEVICE_CLASS_AUDIO_IOCTL_GET_ARG: + + /* Properly cast the parameter pointer. */ + pptr_parameter = (VOID **) parameter; + + /* Save argument. */ + *pptr_parameter = audio -> ux_device_class_audio_callbacks.ux_device_class_audio_arg; + + break; + + default: + + /* Function not supported. Return an error. */ + status = UX_FUNCTION_NOT_SUPPORTED; + } + + /* Return status to caller. */ + return(status); + +} + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_read_frame_free.c b/common/usbx_device_classes/src/ux_device_class_audio_read_frame_free.c new file mode 100644 index 0000000..b03a0fd --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_read_frame_free.c @@ -0,0 +1,124 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_read_frame_free PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function free access buffer for transfer in the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_read_frame_free(UX_DEVICE_CLASS_AUDIO_STREAM *stream) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UCHAR *next_frame; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Underflow!! */ + if (stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length == 0) + { + return(UX_BUFFER_OVERFLOW); + } + + /* Calculate next frame. */ + if (stream -> ux_device_class_audio_stream_access_pos != stream -> ux_device_class_audio_stream_transfer_pos) + { + next_frame = (UCHAR *)stream -> ux_device_class_audio_stream_access_pos; + next_frame += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_frame >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_frame = stream -> ux_device_class_audio_stream_buffer; + + /* Re-free current frame. */ + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length = 0; + + /* Move to next frame. */ + stream -> ux_device_class_audio_stream_access_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_frame; + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos = 0; + } + else + + /* Just re-free current frame. */ + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length = 0; + + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_read_frame_get.c b/common/usbx_device_classes/src/ux_device_class_audio_read_frame_get.c new file mode 100644 index 0000000..d5ed96f --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_read_frame_get.c @@ -0,0 +1,112 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_read_frame_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtain frame access pointer from the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* frame_data Pointer to buffer to save */ +/* pointer to frame data */ +/* frame_length Pointer to buffer to save */ +/* pointer to frame length */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_read_frame_get(UX_DEVICE_CLASS_AUDIO_STREAM *stream, + UCHAR **frame_data, ULONG *frame_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Underflow!! */ + if (stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length == 0) + { + return(UX_BUFFER_OVERFLOW); + } + + /* Obtain frame structure pointer. */ + *frame_data = stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_data; + *frame_length = stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length; + + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_read_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_audio_read_thread_entry.c new file mode 100644 index 0000000..7f668d4 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_read_thread_entry.c @@ -0,0 +1,170 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_read_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is thread of ISO OUT from the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* audio_stream Address of audio stream */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler System error trap */ +/* _ux_utility_thread_suspend Suspend thread used */ +/* _ux_device_stack_transfer_request Issue transfer request */ +/* _ux_utility_memory_copy Copy data */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_audio_read_thread_entry(ULONG audio_stream) +{ + +UINT status; +UX_DEVICE_CLASS_AUDIO_STREAM *stream; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *next_pos; +UX_DEVICE_CLASS_AUDIO_FRAME *next_frame; +ULONG max_packet_size; +ULONG transactions; +ULONG actual_length; + + + /* Get Audio class instance. */ + UX_THREAD_EXTENSION_PTR_GET(stream, UX_DEVICE_CLASS_AUDIO_STREAM, audio_stream) + + /* Get stack device instance. */ + device = stream -> ux_device_class_audio_stream_audio -> ux_device_class_audio_device; + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + max_packet_size = 0; + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Get endpoint instance. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + + /* Endpoint not available, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + break; + + /* Calculate transfer size based on packet size and number transactions once endpoint is available. */ + if (max_packet_size == 0) + { + max_packet_size = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize & 0x7FF; + transactions = (endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize >> 11) & 0x3; + if (transactions) + max_packet_size *= (transactions + 1); + } + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Start frame transfer anyway. */ + status = _ux_device_stack_transfer_request(transfer, max_packet_size, max_packet_size); + + /* Check error. */ + if (status != UX_SUCCESS) + { + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + break; + } + + /* Get actual transfer length. */ + actual_length = transfer -> ux_slave_transfer_request_actual_length; + + /* Frame received, log it. */ + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length = actual_length; + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_pos = 0; + _ux_utility_memory_copy(stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_data, + transfer -> ux_slave_transfer_request_data_pointer, + actual_length); + + /* For simple, do not advance the transfer position if there is overflow. */ + next_pos = (UCHAR *)stream -> ux_device_class_audio_stream_transfer_pos; + next_pos += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_pos >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_pos = stream -> ux_device_class_audio_stream_buffer; + next_frame = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_pos; + + /* Check overflow! */ + if (next_frame -> ux_device_class_audio_frame_length > 0) + { + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } + else + + /* Update transfer position. */ + stream -> ux_device_class_audio_stream_transfer_pos = next_frame; + + /* Invoke notification callback. */ + if (stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done != UX_NULL) + stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done(stream, actual_length); + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module or when a change of alternate setting happens. */ + _ux_utility_thread_suspend(&stream -> ux_device_class_audio_stream_thread); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_reception_start.c b/common/usbx_device_classes/src/ux_device_class_audio_reception_start.c new file mode 100644 index 0000000..6a471fe --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_reception_start.c @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_reception_start PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function start receiving frames in the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_thread_resume Resume thread used */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_reception_start(UX_DEVICE_CLASS_AUDIO_STREAM *stream) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Check if overflow. */ + if (stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length > 0) + return(UX_BUFFER_OVERFLOW); + + /* Start read thread. */ + _ux_utility_thread_resume(&stream -> ux_device_class_audio_stream_thread); + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_sample_read16.c b/common/usbx_device_classes/src/ux_device_class_audio_sample_read16.c new file mode 100644 index 0000000..f218054 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_sample_read16.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_sample_read16 PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads 16-bit sample value from the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* buffer Pointer to buffer to save */ +/* sample data */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_sample_read16(UX_DEVICE_CLASS_AUDIO_STREAM *stream, + USHORT *buffer) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UCHAR *sample_ptr; +UCHAR *next_frame_buffer; +ULONG next_frame_sample; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Underflow!! */ + if (stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length == 0) + { + return(UX_BUFFER_OVERFLOW); + } + + /* Try to read a sample. */ + sample_ptr = stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_data + + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos; + if (buffer) + *buffer = *(USHORT *)(sample_ptr); + + /* Update sample read state. */ + next_frame_sample = stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos + 2; + if (next_frame_sample >= stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length) + { + + /* Set frame length to 0 to indicate no data. */ + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length = 0; + + /* Move to next frame buffer. */ + next_frame_sample = 0; + + /* Move frame if it's not the last one. */ + if (stream -> ux_device_class_audio_stream_access_pos != stream -> ux_device_class_audio_stream_transfer_pos) + { + next_frame_buffer = (UCHAR *)stream -> ux_device_class_audio_stream_access_pos; + next_frame_buffer += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_frame_buffer >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_frame_buffer = stream -> ux_device_class_audio_stream_buffer; + stream -> ux_device_class_audio_stream_access_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_frame_buffer; + } + } + + /* Update next sample position. */ + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos = next_frame_sample; + + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_sample_read24.c b/common/usbx_device_classes/src/ux_device_class_audio_sample_read24.c new file mode 100644 index 0000000..1ce43fd --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_sample_read24.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_sample_read24 PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads 24-bit sample value from the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* buffer Pointer to buffer to save */ +/* sample data */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_sample_read24(UX_DEVICE_CLASS_AUDIO_STREAM *stream, + ULONG *buffer) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UCHAR *sample_ptr; +UCHAR *next_frame_buffer; +ULONG next_frame_sample; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Underflow!! */ + if (stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length == 0) + { + return(UX_BUFFER_OVERFLOW); + } + + /* Try to read a sample. */ + sample_ptr = stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_data + + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos; + if (buffer) + *buffer = sample_ptr[0] + ((ULONG)sample_ptr[1] << 8) + ((ULONG)sample_ptr[2] << 16); + + /* Update sample read state. */ + next_frame_sample = stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos + 3; + if (next_frame_sample >= stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length) + { + + /* Set frame length to 0 to indicate no data. */ + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length = 0; + + /* Move to next frame buffer. */ + next_frame_sample = 0; + + /* Move frame if it's not the last one. */ + if (stream -> ux_device_class_audio_stream_access_pos != stream -> ux_device_class_audio_stream_transfer_pos) + { + next_frame_buffer = (UCHAR *)stream -> ux_device_class_audio_stream_access_pos; + next_frame_buffer += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_frame_buffer >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_frame_buffer = stream -> ux_device_class_audio_stream_buffer; + stream -> ux_device_class_audio_stream_access_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_frame_buffer; + } + } + + /* Update next sample position. */ + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos = next_frame_sample; + + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_sample_read32.c b/common/usbx_device_classes/src/ux_device_class_audio_sample_read32.c new file mode 100644 index 0000000..e0ecc6d --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_sample_read32.c @@ -0,0 +1,143 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_sample_read32 PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads 32-bit sample from the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* buffer Pointer to buffer to save */ +/* sample data */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_sample_read32(UX_DEVICE_CLASS_AUDIO_STREAM *stream, ULONG *buffer) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UCHAR *sample_ptr; +UCHAR *next_frame_buffer; +ULONG next_frame_sample; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Underflow!! */ + if (stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length == 0) + { + return(UX_BUFFER_OVERFLOW); + } + + /* Try to read a sample. */ + sample_ptr = stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_data + + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos; + if (buffer) + *buffer = *(ULONG *)(sample_ptr); + + /* Update sample read state. */ + next_frame_sample = stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos + 4; + if (next_frame_sample >= stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length) + { + + /* Set frame length to 0 to indicate no data. */ + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length = 0; + + /* Move to next frame buffer. */ + next_frame_sample = 0; + + /* Move frame if it's not the last one. */ + if (stream -> ux_device_class_audio_stream_access_pos != stream -> ux_device_class_audio_stream_transfer_pos) + { + next_frame_buffer = (UCHAR *)stream -> ux_device_class_audio_stream_access_pos; + next_frame_buffer += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_frame_buffer >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_frame_buffer = stream -> ux_device_class_audio_stream_buffer; + stream -> ux_device_class_audio_stream_access_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_frame_buffer; + } + } + + /* Update next sample position. */ + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos = next_frame_sample; + + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_sample_read8.c b/common/usbx_device_classes/src/ux_device_class_audio_sample_read8.c new file mode 100644 index 0000000..580d28c --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_sample_read8.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_sample_read8 PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads 8-bit sample from the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* buffer Pointer to buffer to save */ +/* sample data */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_sample_read8(UX_DEVICE_CLASS_AUDIO_STREAM *stream, + UCHAR *buffer) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UCHAR *sample_ptr; +UCHAR *next_frame_buffer; +ULONG next_frame_sample; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Underflow!! */ + if (stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length == 0) + { + return(UX_BUFFER_OVERFLOW); + } + + /* Try to read a sample. */ + sample_ptr = stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_data + + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos; + if (buffer) + *buffer = *sample_ptr; + + /* Update sample read state. */ + next_frame_sample = stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos + 1; + if (next_frame_sample >= stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length) + { + + /* Set frame length to 0 to indicate no data. */ + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length = 0; + + /* Move to next frame buffer. */ + next_frame_sample = 0; + + /* Move frame if it's not the last one. */ + if (stream -> ux_device_class_audio_stream_access_pos != stream -> ux_device_class_audio_stream_transfer_pos) + { + next_frame_buffer = (UCHAR *)stream -> ux_device_class_audio_stream_access_pos; + next_frame_buffer += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_frame_buffer >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_frame_buffer = stream -> ux_device_class_audio_stream_buffer; + stream -> ux_device_class_audio_stream_access_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_frame_buffer; + } + } + + /* Update next sample position. */ + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_pos = next_frame_sample; + + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_stream_get.c b/common/usbx_device_classes/src/ux_device_class_audio_stream_get.c new file mode 100644 index 0000000..4072478 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_stream_get.c @@ -0,0 +1,93 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_stream_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function get the stream instance of Audio class. */ +/* */ +/* INPUT */ +/* */ +/* audio Address of audio class */ +/* instance */ +/* stream_index Stream instance index 0 based */ +/* stream Pointer to buffer to fill */ +/* pointer to stream instance */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_thread_delete Delete thread used */ +/* _ux_utility_memory_free Free used local memory */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_stream_get(UX_DEVICE_CLASS_AUDIO *audio, + ULONG stream_index, UX_DEVICE_CLASS_AUDIO_STREAM **stream) +{ + + + /* Sanity check. */ + if (audio == UX_NULL) + return(UX_ERROR); + + /* Index validation. */ + if (stream_index >= audio -> ux_device_class_audio_streams_nb) + return(UX_ERROR); + + /* Store the stream instance found. */ + if (stream) + *stream = audio -> ux_device_class_audio_streams + stream_index; + + /* Return completion status. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_transmission_start.c b/common/usbx_device_classes/src/ux_device_class_audio_transmission_start.c new file mode 100644 index 0000000..31d8480 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_transmission_start.c @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_transmission_start PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function start sending valid frames in the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_thread_resume Resume thread used */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_transmission_start(UX_DEVICE_CLASS_AUDIO_STREAM *stream) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Check if there is frame to send (underflow). */ + if (stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length == 0) + return(UX_BUFFER_OVERFLOW); + + /* Start write thread. */ + _ux_utility_thread_resume(&stream -> ux_device_class_audio_stream_thread); + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_unitialize.c b/common/usbx_device_classes/src/ux_device_class_audio_unitialize.c new file mode 100644 index 0000000..28886dd --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_unitialize.c @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_uninitialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function uninitialize the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_thread_delete Delete thread used */ +/* _ux_utility_memory_free Free used local memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_uninitialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_DEVICE_CLASS_AUDIO *audio; +UX_DEVICE_CLASS_AUDIO_STREAM *stream; +UX_SLAVE_CLASS *class; +ULONG i; + + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + audio = (UX_DEVICE_CLASS_AUDIO *) class -> ux_slave_class_instance; + + /* Sanity check. */ + if (audio != UX_NULL) + { + + /* Free the stream resources. */ + stream = (UX_DEVICE_CLASS_AUDIO_STREAM *)((UCHAR *)audio + sizeof(UX_DEVICE_CLASS_AUDIO)); + for (i = 0; i < audio -> ux_device_class_audio_streams_nb; i ++) + { + _ux_utility_thread_delete(&stream -> ux_device_class_audio_stream_thread); + _ux_utility_memory_free(stream -> ux_device_class_audio_stream_thread_stack); + _ux_utility_memory_free(stream -> ux_device_class_audio_stream_buffer); + } + + /* Free the audio instance with controls and streams. */ + _ux_utility_memory_free(audio); + } + + /* Return completion status. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_audio_write_frame_commit.c b/common/usbx_device_classes/src/ux_device_class_audio_write_frame_commit.c new file mode 100644 index 0000000..f8efba5 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_write_frame_commit.c @@ -0,0 +1,126 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_write_frame_commit PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function set frame buffer valid to send in the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* buffer Pointer to buffer to save */ +/* frame data */ +/* length Frame length in bytes */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_write_frame_commit(UX_DEVICE_CLASS_AUDIO_STREAM *stream, ULONG length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UCHAR *next_pos; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Check overflow!! */ + if (stream -> ux_device_class_audio_stream_access_pos == stream -> ux_device_class_audio_stream_transfer_pos && + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length != 0) + return(UX_BUFFER_OVERFLOW); + + /* Check frame length. */ + if (stream -> ux_device_class_audio_stream_frame_buffer_size < length) + return(UX_ERROR); + + /* Calculate next frame buffer. */ + next_pos = (UCHAR *)stream -> ux_device_class_audio_stream_access_pos; + next_pos += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_pos >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_pos = stream -> ux_device_class_audio_stream_buffer; + + /* Commit frame length. */ + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length = length; + + /* Move frame position. */ + stream -> ux_device_class_audio_stream_access_pos = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_pos; + + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_write_frame_get.c b/common/usbx_device_classes/src/ux_device_class_audio_write_frame_get.c new file mode 100644 index 0000000..5ad7945 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_write_frame_get.c @@ -0,0 +1,113 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_write_frame_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function get a writable frame buffer in the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* stream Address of audio stream */ +/* instance */ +/* frame Pointer to buffer to save */ +/* frame buffer pointer */ +/* length Pointer to save frame */ +/* buffer length in bytes */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_audio_write_frame_get(UX_DEVICE_CLASS_AUDIO_STREAM *stream, UCHAR **frame, ULONG *length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check if endpoint is available. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + if (endpoint == UX_NULL) + return(UX_ERROR); + + /* Check if endpoint direction is OK. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) + return(UX_ERROR); + + /* Check overflow!! */ + if (stream -> ux_device_class_audio_stream_access_pos == stream -> ux_device_class_audio_stream_transfer_pos && + stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_length != 0) + return(UX_BUFFER_OVERFLOW); + + /* Store frame buffer pointer. */ + *frame = stream -> ux_device_class_audio_stream_access_pos -> ux_device_class_audio_frame_data; + + /* Exclude header size in frame buffer size. */ + *length = stream -> ux_device_class_audio_stream_frame_buffer_size - 8; + + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_audio_write_thread_entry.c b/common/usbx_device_classes/src/ux_device_class_audio_write_thread_entry.c new file mode 100644 index 0000000..a246cf1 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_audio_write_thread_entry.c @@ -0,0 +1,172 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_audio.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_audio_write_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is thread of ISO IN for the Audio class. */ +/* */ +/* INPUT */ +/* */ +/* audio_stream Address of audio stream */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler System error trap */ +/* _ux_utility_thread_suspend Suspend thread used */ +/* _ux_device_stack_transfer_request Issue transfer request */ +/* _ux_utility_memory_copy Copy data */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_audio_write_thread_entry(ULONG audio_stream) +{ + +UINT status; +UX_DEVICE_CLASS_AUDIO_STREAM *stream; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_TRANSFER *transfer; +UCHAR *next_pos; +UX_DEVICE_CLASS_AUDIO_FRAME *next_frame; +ULONG transfer_length; +ULONG actual_length; + + + /* Get Audio class stream instance. */ + UX_THREAD_EXTENSION_PTR_GET(stream, UX_DEVICE_CLASS_AUDIO_STREAM, audio_stream) + + /* Get stack device instance. */ + device = stream -> ux_device_class_audio_stream_audio -> ux_device_class_audio_device; + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Get endpoint instance. */ + endpoint = stream -> ux_device_class_audio_stream_endpoint; + + /* Endpoint not available, maybe it's alternate setting 0. */ + if (endpoint == UX_NULL) + break; + + /* Get transfer instance. */ + transfer = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Start frame transfer anyway (even ZLP). */ + transfer_length = stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length; + if (transfer_length) + _ux_utility_memory_copy(transfer -> ux_slave_transfer_request_data_pointer, + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_data, transfer_length); + + /* Issue transfer request, thread blocked until transfer done. */ + status = _ux_device_stack_transfer_request(transfer, transfer_length, transfer_length); + + /* Check error. */ + if (status != UX_SUCCESS) + { + + /* Error notification! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_ERROR); + break; + } + + /* Frame sent, free it. */ + stream -> ux_device_class_audio_stream_transfer_pos -> ux_device_class_audio_frame_length = 0; + + /* Get actual transfer length. */ + actual_length = transfer -> ux_slave_transfer_request_actual_length; + + /* Calculate next position. */ + next_pos = (UCHAR *)stream -> ux_device_class_audio_stream_transfer_pos; + next_pos += stream -> ux_device_class_audio_stream_frame_buffer_size; + if (next_pos >= stream -> ux_device_class_audio_stream_buffer + stream -> ux_device_class_audio_stream_buffer_size) + next_pos = stream -> ux_device_class_audio_stream_buffer; + next_frame = (UX_DEVICE_CLASS_AUDIO_FRAME *)next_pos; + + /* Underflow check! */ + if (transfer_length) + { + + /* Advance position. */ + stream -> ux_device_class_audio_stream_transfer_pos = next_frame; + + /* Error trap! */ + if (next_frame -> ux_device_class_audio_frame_length == 0) + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } + else + { + + /* Advance position if next frame available. */ + if (next_frame -> ux_device_class_audio_frame_length) + stream -> ux_device_class_audio_stream_transfer_pos = next_frame; + else + + /* Error trap! */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } + + /* Invoke notification callback. */ + if (stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done != UX_NULL) + stream -> ux_device_class_audio_stream_callbacks.ux_device_class_audio_stream_frame_done(stream, actual_length); + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module or when a change of alternate setting happens. */ + _ux_utility_thread_suspend(&stream -> ux_device_class_audio_stream_thread); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_activate.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_activate.c new file mode 100644 index 0000000..58c5f4b --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_activate.c @@ -0,0 +1,106 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB CDC device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to cdc_acm command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_activate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_CDC_ACM *cdc_acm; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + cdc_acm = (UX_SLAVE_CLASS_CDC_ACM *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Store the class instance into the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)cdc_acm; + + /* Now the opposite, store the interface in the class instance. */ + cdc_acm -> ux_slave_class_cdc_acm_interface = interface; + + /* If there is a activate function call it. */ + if (cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_instance_activate != UX_NULL) + { + /* Invoke the application. */ + cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_instance_activate(cdc_acm); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ACM_ACTIVATE, cdc_acm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, cdc_acm, 0, 0, 0) + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c new file mode 100644 index 0000000..9d0e4bc --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkin_thread.c @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_bulkin_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the cdc_acm bulkin endpoint. The bulk*/ +/* IN endpoint is used when the device wants to write data to be sent */ +/* to the host. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm_class Address of cdc_acm class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_cdc_acm_bulkin_thread(ULONG cdc_acm_class) +{ + +UX_SLAVE_CLASS_CDC_ACM *cdc_acm; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; +ULONG actual_flags; +ULONG transfer_length; +ULONG total_length; +ULONG sent_length; + + + /* Get the cdc_acm instance from this class container. */ + UX_THREAD_EXTENSION_PTR_GET(cdc_acm, UX_SLAVE_CLASS_CDC_ACM, cdc_acm_class) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* This is the first time we are activated. We need the interface to the class. */ + interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* So the next endpoint has to be the IN endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + + /* Get the transfer request for the bulk IN pipe. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Wait until we have a event sent by the application. */ + status = _ux_utility_event_flags_get(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group, UX_DEVICE_CLASS_CDC_ACM_WRITE_EVENT, + TX_OR_CLEAR, &actual_flags, TX_WAIT_FOREVER); + + /* Check the completion code. */ + if (status == UX_SUCCESS) + { + + /* Get the length of the entire buffer to send. */ + total_length = cdc_acm -> ux_slave_class_cdc_acm_callback_total_length; + + /* Duplicate the data pointer to keep a current pointer. */ + cdc_acm -> ux_slave_class_cdc_acm_callback_current_data_pointer = cdc_acm -> ux_slave_class_cdc_acm_callback_data_pointer; + + /* Reset sent length. */ + sent_length = 0; + + /* Special ZLP case. */ + if (total_length == 0) + + /* Send the zlp to the host. */ + status = _ux_device_stack_transfer_request(transfer_request, 0, 0); + + else + { + + /* We should send the total length. But we may have a case of ZLP. */ + while (total_length) + { + + /* Check the length remaining to send. */ + if (total_length > endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize) + + /* We can't fit all the length. */ + transfer_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize; + + else + + /* We can send everything. */ + transfer_length = total_length; + + /* Copy the payload locally. */ + _ux_utility_memory_copy (transfer_request -> ux_slave_transfer_request_data_pointer, + cdc_acm -> ux_slave_class_cdc_acm_callback_current_data_pointer, + transfer_length); + + /* Send the acm payload to the host. */ + status = _ux_device_stack_transfer_request(transfer_request, transfer_length, transfer_length); + + /* Check the status. */ + if (status != UX_SUCCESS) + { + + /* Reset total_length as we need to get out of loop. */ + total_length = 0; + } + else + { + + /* Update sent length. */ + sent_length += transfer_length; + + /* Decrement length to be sent. */ + total_length -= transfer_length; + + /* And update the current pointer. */ + cdc_acm -> ux_slave_class_cdc_acm_callback_current_data_pointer += transfer_length; + } + } + } + + /* Schedule of transmission was completed. */ + cdc_acm -> ux_slave_class_cdc_acm_scheduled_write = UX_FALSE; + + /* We get here when the entire user data payload has been sent or if there is an error. */ + /* If there is a callback defined by the application, send the transaction event to it. */ + if (cdc_acm -> ux_device_class_cdc_acm_write_callback != UX_NULL) + + /* Callback exists. */ + cdc_acm -> ux_device_class_cdc_acm_write_callback(cdc_acm, status, sent_length); + + /* Now we return to wait for an event from the application or the user to stop the transmission. */ + } + else + { + break; + } + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module or when a change of alternate setting happens. */ + _ux_utility_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c new file mode 100644 index 0000000..5ca343f --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_bulkout_thread.c @@ -0,0 +1,149 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_bulkout_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the cdc_acm bulk out endpoint. It */ +/* is waiting for the host to send data on the bulk out endpoint to */ +/* the device. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm_class Address of cdc_acm class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_cdc_acm_bulkout_thread(ULONG cdc_acm_class) +{ + +UX_SLAVE_CLASS_CDC_ACM *cdc_acm; +UX_SLAVE_DEVICE *device; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; + + /* Cast properly the cdc_acm instance. */ + UX_THREAD_EXTENSION_PTR_GET(cdc_acm, UX_SLAVE_CLASS_CDC_ACM, cdc_acm_class) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* This is the first time we are activated. We need the interface to the class. */ + interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if OUT we have the correct endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + { + + /* So the next endpoint has to be the OUT endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* This thread runs forever but can be suspended or resumed by the user application. */ + while(1) + { + + /* Select the transfer request associated with BULK OUT endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize, + endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize); + + /* Check the completion code. */ + if (status == UX_SUCCESS) + { + + /* Check the state of the transfer. If there is an error, we do not proceed with this report. */ + if (transfer_request -> ux_slave_transfer_request_completion_code == UX_SUCCESS) + { + + /* If there is a callback defined by the application, send the transaction event to it. */ + if (cdc_acm -> ux_device_class_cdc_acm_read_callback != UX_NULL) + + /* Callback exists. */ + cdc_acm -> ux_device_class_cdc_acm_read_callback(cdc_acm, UX_SUCCESS, transfer_request -> ux_slave_transfer_request_data_pointer, + transfer_request -> ux_slave_transfer_request_actual_length); + + } + else + { + + /* We have an error. If there is a callback defined by the application, send the transaction event to it. */ + if (cdc_acm -> ux_device_class_cdc_acm_read_callback != UX_NULL) + + /* Callback exists. */ + cdc_acm -> ux_device_class_cdc_acm_read_callback(cdc_acm, status, UX_NULL, 0); + + } + } + } + + /* We need to suspend ourselves. We will be resumed by the application if needed. */ + _ux_utility_thread_suspend(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_control_request.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_control_request.c new file mode 100644 index 0000000..8ae6921 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_control_request.c @@ -0,0 +1,179 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_control_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Pointer to cdc_acm class */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* CDC Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_control_request(UX_SLAVE_CLASS_COMMAND *command) +{ +UX_SLAVE_CLASS_CDC_ACM *cdc_acm; +UX_SLAVE_CLASS *class; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +ULONG request; +ULONG value; +ULONG request_length; +ULONG transmit_length; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + cdc_acm = (UX_SLAVE_CLASS_CDC_ACM *) class -> ux_slave_class_instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the pointer to the transfer request associated with the control endpoint. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Extract all necessary fields of the request. */ + request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST); + + /* Extract all necessary fields of the value. */ + value = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE); + + /* Pickup the request length. */ + request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH); + + transmit_length = request_length ; + + /* Here we proceed only the standard request we know of at the device level. */ + switch (request) + { + + case UX_SLAVE_CLASS_CDC_ACM_SET_CONTROL_LINE_STATE: + + /* Reset current line state values. */ + cdc_acm -> ux_slave_class_cdc_acm_data_dtr_state = 0; + cdc_acm -> ux_slave_class_cdc_acm_data_rts_state = 0; + + /* Get the line state parameters from the host. DTR signal. */ + if (value & UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_DTR) + cdc_acm -> ux_slave_class_cdc_acm_data_dtr_state = UX_TRUE; + + /* Get the line state parameters from the host. RTS signal. */ + if (value & UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_RTS) + cdc_acm -> ux_slave_class_cdc_acm_data_rts_state = UX_TRUE; + + /* If there is a parameter change function call it. */ + if (cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_parameter_change != UX_NULL) + { + + /* Invoke the application. */ + cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_parameter_change(cdc_acm); + } + + break ; + + case UX_SLAVE_CLASS_CDC_ACM_GET_LINE_CODING: + + /* Setup the length appropriately. */ + if (request_length > UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_RESPONSE_SIZE) + transmit_length = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_RESPONSE_SIZE; + + /* Send the line coding default parameters back to the host. */ + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_BAUDRATE_STRUCT, + cdc_acm -> ux_slave_class_cdc_acm_baudrate); + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_STOP_BIT_STRUCT) = cdc_acm -> ux_slave_class_cdc_acm_stop_bit; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARITY_STRUCT) = cdc_acm -> ux_slave_class_cdc_acm_parity; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_DATA_BIT_STRUCT) = cdc_acm -> ux_slave_class_cdc_acm_data_bit; + + /* Set the phase of the transfer to data out. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* Perform the data transfer. */ + _ux_device_stack_transfer_request(transfer_request, transmit_length, request_length); + break; + + case UX_SLAVE_CLASS_CDC_ACM_SET_LINE_CODING: + + /* Get the line coding parameters from the host. */ + cdc_acm -> ux_slave_class_cdc_acm_baudrate = _ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_BAUDRATE_STRUCT); + cdc_acm -> ux_slave_class_cdc_acm_stop_bit = *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_STOP_BIT_STRUCT); + cdc_acm -> ux_slave_class_cdc_acm_parity = *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARITY_STRUCT); + cdc_acm -> ux_slave_class_cdc_acm_data_bit = *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_DATA_BIT_STRUCT); + + /* If there is a parameter change function call it. */ + if (cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_parameter_change != UX_NULL) + { + + /* Invoke the application. */ + cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_parameter_change(cdc_acm); + } + + break ; + + default: + + /* Unknown function. It's not handled. */ + return(UX_ERROR); + } + + /* It's handled. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_deactivate.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_deactivate.c new file mode 100644 index 0000000..dc132e1 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_deactivate.c @@ -0,0 +1,136 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivate an instance of the cdc_acm class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_all_request_abort Abort all transfers */ +/* _ux_device_class_cdc_acm_ioctl IO control */ +/* */ +/* CALLED BY */ +/* */ +/* CDC Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_deactivate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_CDC_ACM *cdc_acm; +UX_SLAVE_ENDPOINT *endpoint_in; +UX_SLAVE_ENDPOINT *endpoint_out; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + cdc_acm = (UX_SLAVE_CLASS_CDC_ACM *) class -> ux_slave_class_instance; + + /* We need the interface to the class. */ + interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint_in = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint_in -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* Wrong direction, we found the OUT endpoint first. */ + endpoint_out = endpoint_in; + + /* So the next endpoint has to be the IN endpoint. */ + endpoint_in = endpoint_out -> ux_slave_endpoint_next_endpoint; + } + else + { + + /* We found the endpoint IN first, so next endpoint is OUT. */ + endpoint_out = endpoint_in -> ux_slave_endpoint_next_endpoint; + } + + /* Terminate the transactions pending on the endpoints. */ + _ux_device_stack_transfer_all_request_abort(endpoint_in, UX_TRANSFER_BUS_RESET); + _ux_device_stack_transfer_all_request_abort(endpoint_out, UX_TRANSFER_BUS_RESET); + + /* Terminate transmission and free resources. */ + _ux_device_class_cdc_acm_ioctl(cdc_acm, UX_SLAVE_CLASS_CDC_ACM_IOCTL_TRANSMISSION_STOP, UX_NULL); + + /* If there is a deactivate function call it. */ + if (cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_instance_deactivate != UX_NULL) + { + + /* Invoke the application. */ + cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_instance_deactivate(cdc_acm); + } + + /* We need to reset the DTR and RTS values so they do not carry over to the + next connection. */ + cdc_acm -> ux_slave_class_cdc_acm_data_dtr_state = 0; + cdc_acm -> ux_slave_class_cdc_acm_data_rts_state = 0; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ACM_DEACTIVATE, cdc_acm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(cdc_acm); + + /* Return completion status. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_entry.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_entry.c new file mode 100644 index 0000000..1cf3e63 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_entry.c @@ -0,0 +1,147 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_class_device_cdc_acm_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the cdc_acm class. It */ +/* will be called by the device stack enumeration module when the */ +/* host has sent a SET_CONFIGURATION command and the cdc_acm interface */ +/* needs to be mounted. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_cdc_acm_initialize Initialize cdc_acm class */ +/* _ux_device_class_cdc_acm_uninitialize Uninitialize cdc_acm class*/ +/* _ux_device_class_cdc_acm_activate Activate cdc_acm class */ +/* _ux_device_class_cdc_acm_deactivate Deactivate cdc_acm class */ +/* _ux_device_class_cdc_acm_control_request Request control */ +/* */ +/* CALLED BY */ +/* */ +/* CDC Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_entry(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_slave_class_command_request) + { + + case UX_SLAVE_CLASS_COMMAND_INITIALIZE: + + /* Call the init function of the CDC ACM class. */ + status = _ux_device_class_cdc_acm_initialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_UNINITIALIZE: + + /* Call the init function of the CDC ACM class. */ + status = _ux_device_class_cdc_acm_uninitialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_QUERY: + + /* Check the CLASS definition in the interface descriptor. */ + if (command -> ux_slave_class_command_class == UX_SLAVE_CLASS_CDC_ACM_CLASS) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_SLAVE_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the host has sent a SET_CONFIGURATION command + and this interface has to be mounted. Both Bulk endpoints have to be mounted + and the cdc_acm thread needs to be activated. */ + status = _ux_device_class_cdc_acm_activate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted. + The device endpoints have to be dismounted and the cdc_acm thread canceled. */ + status = _ux_device_class_cdc_acm_deactivate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_REQUEST: + + /* The request command is used when the host sends a command on the control endpoint. */ + status = _ux_device_class_cdc_acm_control_request(command); + + /* Return the completion status. */ + return(status); + + default: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c new file mode 100644 index 0000000..e858c2c --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_initialize.c @@ -0,0 +1,140 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB CDC device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to cdc_acm command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_mutex_create Create mutex */ +/* _ux_utility_mutex_delete Delete mutex */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_initialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_CDC_ACM *cdc_acm; +UX_SLAVE_CLASS_CDC_ACM_PARAMETER *cdc_acm_parameter; +UX_SLAVE_CLASS *class; +UINT status; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Create an instance of the device cdc_acm class. */ + cdc_acm = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_CDC_ACM)); + + /* Check for successful allocation. */ + if (cdc_acm == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save the address of the CDC instance inside the CDC container. */ + class -> ux_slave_class_instance = (VOID *) cdc_acm; + + /* Get the pointer to the application parameters for the cdc_acm class. */ + cdc_acm_parameter = command -> ux_slave_class_command_parameter; + + /* Store the start and stop signals if needed by the application. */ + cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_instance_activate = cdc_acm_parameter -> ux_slave_class_cdc_acm_instance_activate; + cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_instance_deactivate = cdc_acm_parameter -> ux_slave_class_cdc_acm_instance_deactivate; + cdc_acm -> ux_slave_class_cdc_acm_parameter.ux_slave_class_cdc_acm_parameter_change = cdc_acm_parameter -> ux_slave_class_cdc_acm_parameter_change; + + /* Create the Mutex for each endpoint as multiple threads cannot access each pipe at the same time. */ + status = _ux_utility_mutex_create(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex, "ux_slave_class_cdc_acm_in_mutex"); + + /* Check Mutex creation error. */ + if(status != UX_SUCCESS) + { + + /* Free the resources. */ + _ux_utility_memory_free(cdc_acm); + + /* Return fatal error. */ + return(UX_MUTEX_ERROR); + } + + /* Out Mutex. */ + status = _ux_utility_mutex_create(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex, "ux_slave_class_cdc_acm_out_mutex"); + + /* Check Mutex creation error. */ + if(status != UX_SUCCESS) + { + + /* Delete the endpoint IN mutex. */ + _ux_utility_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex); + + /* Free the resources. */ + _ux_utility_memory_free(cdc_acm); + + /* Return fatal error. */ + return(UX_MUTEX_ERROR); + } + + /* Update the line coding fields with default values. */ + cdc_acm -> ux_slave_class_cdc_acm_baudrate = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_BAUDRATE; + cdc_acm -> ux_slave_class_cdc_acm_stop_bit = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_STOP_BIT; + cdc_acm -> ux_slave_class_cdc_acm_parity = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARITY; + cdc_acm -> ux_slave_class_cdc_acm_data_bit = UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_DATA_BIT; + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c new file mode 100644 index 0000000..3aacab0 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_ioctl.c @@ -0,0 +1,428 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_ioctl PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs certain functions on the cdc acm instance */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Address of cdc_acm class */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_abort Abort transfer */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_event_flags_create Create event flags */ +/* _ux_utility_event_flags_delete Delete event flags */ +/* _ux_utility_thread_create Create thread */ +/* _ux_utility_thread_delete Delete thread */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_ioctl(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, ULONG ioctl_function, + VOID *parameter) +{ + +UINT status; +UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARAMETER *line_coding; +UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER *line_state; +UX_SLAVE_CLASS_CDC_ACM_CALLBACK_PARAMETER *callback; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_TRANSFER *transfer_request; + + /* Let's be optimist ! */ + status = UX_SUCCESS; + + /* The command request will tell us what we need to do here. */ + switch (ioctl_function) + { + + case UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING: + + /* Properly cast the parameter pointer. */ + line_coding = (UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARAMETER *) parameter; + + /* Save the parameters in the cdc_acm function. */ + cdc_acm -> ux_slave_class_cdc_acm_baudrate = line_coding -> ux_slave_class_cdc_acm_parameter_baudrate; + cdc_acm -> ux_slave_class_cdc_acm_stop_bit = line_coding -> ux_slave_class_cdc_acm_parameter_stop_bit; + cdc_acm -> ux_slave_class_cdc_acm_parity = line_coding -> ux_slave_class_cdc_acm_parameter_parity; + cdc_acm -> ux_slave_class_cdc_acm_data_bit = line_coding -> ux_slave_class_cdc_acm_parameter_data_bit; + + break; + + case UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING: + + /* Properly cast the parameter pointer. */ + line_coding = (UX_SLAVE_CLASS_CDC_ACM_LINE_CODING_PARAMETER *) parameter; + + /* Save the parameters in the cdc_acm function. */ + line_coding -> ux_slave_class_cdc_acm_parameter_baudrate = cdc_acm -> ux_slave_class_cdc_acm_baudrate; + line_coding -> ux_slave_class_cdc_acm_parameter_stop_bit = cdc_acm -> ux_slave_class_cdc_acm_stop_bit; + line_coding -> ux_slave_class_cdc_acm_parameter_parity = cdc_acm -> ux_slave_class_cdc_acm_parity; + line_coding -> ux_slave_class_cdc_acm_parameter_data_bit = cdc_acm -> ux_slave_class_cdc_acm_data_bit; + + break; + + + case UX_SLAVE_CLASS_CDC_ACM_IOCTL_GET_LINE_STATE: + + /* Properly cast the parameter pointer. */ + line_state = (UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER *) parameter; + + /* Return the DTR/RTS signals. */ + line_state -> ux_slave_class_cdc_acm_parameter_rts = cdc_acm -> ux_slave_class_cdc_acm_data_rts_state; + line_state -> ux_slave_class_cdc_acm_parameter_dtr = cdc_acm -> ux_slave_class_cdc_acm_data_dtr_state; + + break; + + case UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE: + + /* Properly cast the parameter pointer. */ + line_state = (UX_SLAVE_CLASS_CDC_ACM_LINE_STATE_PARAMETER *) parameter; + + /* Set the DTR/RTS signals. */ + cdc_acm -> ux_slave_class_cdc_acm_data_rts_state = line_state -> ux_slave_class_cdc_acm_parameter_rts; + cdc_acm -> ux_slave_class_cdc_acm_data_dtr_state = line_state -> ux_slave_class_cdc_acm_parameter_dtr; + + break; + + + case UX_SLAVE_CLASS_CDC_ACM_IOCTL_ABORT_PIPE: + + /* Get the interface from the instance. */ + interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* What direction ? */ + switch( (ULONG) (ALIGN_TYPE) parameter) + { + case UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_XMIT : + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* So the next endpoint has to be the XMIT endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + break; + + case UX_SLAVE_CLASS_CDC_ACM_ENDPOINT_RCV : + + /* Check the endpoint direction, if OUT we have the correct endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + { + + /* So the next endpoint has to be the RCV endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + break; + + + + default : + + /* Parameter not supported. Return an error. */ + status = UX_ENDPOINT_HANDLE_UNKNOWN; + } + + /* Get the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Check the status of the transfer. */ + if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) + { + + /* Abort the transfer. */ + _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); + + } + + break; + + case UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_READ_TIMEOUT: + case UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_WRITE_TIMEOUT: + + /* Get the interface from the instance. */ + interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* If it's reading timeout but endpoint is OUT, it should be the next one. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != + (ULONG)((ioctl_function == UX_SLAVE_CLASS_CDC_ACM_IOCTL_SET_READ_TIMEOUT) ? UX_ENDPOINT_OUT : UX_ENDPOINT_IN)) + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + + /* Get the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Check the status of the transfer. */ + if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) + status = UX_ERROR; + else + transfer_request -> ux_slave_transfer_request_timeout = (ULONG) (ALIGN_TYPE) parameter; + + break; + + case UX_SLAVE_CLASS_CDC_ACM_IOCTL_TRANSMISSION_START: + + + /* Check if we are in callback transmission already. */ + if (cdc_acm -> ux_slave_class_cdc_acm_transmission_status == UX_TRUE) + { + /* We should not to that ! */ + return(UX_ERROR); + + } + + /* Properly cast the parameter pointer. */ + callback = (UX_SLAVE_CLASS_CDC_ACM_CALLBACK_PARAMETER *) parameter; + + /* We need to start the 2 threads for sending and receiving. */ + /* Allocate some memory for the bulk out thread stack. */ + cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack == UX_NULL) + { + + /* Return the status to the caller. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Allocate some memory for the bulk in thread stack. */ + cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack == UX_NULL) + { + + /* Free resources. */ + _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack ); + + /* Return the status to the caller. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Create a event flag group for the cdc_acm class to synchronize with the application writing event . */ + status = _ux_utility_event_flags_create(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group, "ux_device_class_cdc_acm_event_flag"); + + /* Check status. */ + if (status != UX_SUCCESS) + { + + /* Free resources. */ + _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack ); + _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack ); + + /* Do not proceed. */ + return(UX_EVENT_ERROR); + } + + /* Bulk endpoint treatment needs to be running in a different thread. So start + a new thread. We pass a pointer to the cdc_acm instance to the new thread. This thread + does not start until we have a instance of the class. */ + status = _ux_utility_thread_create(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread , "ux_slave_class_cdc_acm_bulkin_thread", + _ux_device_class_cdc_acm_bulkin_thread, + (ULONG) (ALIGN_TYPE) cdc_acm, (VOID *) cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack , + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check the creation of this thread. */ + if (status != UX_SUCCESS) + { + + /* Delete the event flag group for the acm class. */ + _ux_utility_event_flags_delete(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group); + + /* Free some of the resource used. */ + _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack ); + _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack ); + + return(UX_THREAD_ERROR); + } + + UX_THREAD_EXTENSION_PTR_SET(&(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread), cdc_acm) + + /* Bulk endpoint treatment needs to be running in a different thread. So start + a new thread. We pass a pointer to the cdc_acm instance to the new thread. This thread + does not start until we have a instance of the class. */ + status = _ux_utility_thread_create(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread , "ux_slave_class_cdc_acm_bulkout_thread", + _ux_device_class_cdc_acm_bulkout_thread, + (ULONG) (ALIGN_TYPE) cdc_acm, (VOID *) cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack , + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check the creation of this thread. */ + if (status != UX_SUCCESS) + { + + /* Delete the event flag group for the acm class. */ + _ux_utility_event_flags_delete(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group); + + /* Delete bulk in thread. */ + _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); + + /* Free some of the resource used. */ + _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack ); + _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack ); + + return(UX_THREAD_ERROR); + } + + UX_THREAD_EXTENSION_PTR_SET(&(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread), cdc_acm) + + /* Save the callback function for write. */ + cdc_acm -> ux_device_class_cdc_acm_write_callback = callback -> ux_device_class_cdc_acm_parameter_write_callback; + + /* Save the callback function for read. */ + cdc_acm -> ux_device_class_cdc_acm_read_callback = callback -> ux_device_class_cdc_acm_parameter_read_callback; + + /* Declare the transmission with callback on. */ + cdc_acm -> ux_slave_class_cdc_acm_transmission_status = UX_TRUE; + + /* We are done here. */ + return(UX_SUCCESS); + + break; + + case UX_SLAVE_CLASS_CDC_ACM_IOCTL_TRANSMISSION_STOP: + + /* Check if we are in callback transmission already. */ + if (cdc_acm -> ux_slave_class_cdc_acm_transmission_status == UX_TRUE) + { + + /* Get the interface from the instance. */ + interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Get the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Check the status of the transfer. */ + if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) + { + + /* Abort the transfer. */ + _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); + + } + + /* Next endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + + /* Get the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Check the status of the transfer. */ + if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) + { + + /* Abort the transfer. */ + _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); + + } + + /* Terminate threads. */ + _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread); + _ux_utility_thread_delete(&cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread); + + /* Free resources. */ + _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkout_thread_stack ); + _ux_utility_memory_free(cdc_acm -> ux_slave_class_cdc_acm_bulkin_thread_stack ); + + /* Delete the event flag group for the acm class. */ + _ux_utility_event_flags_delete(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group); + + /* Clear scheduled write flag. */ + cdc_acm -> ux_slave_class_cdc_acm_scheduled_write = UX_FALSE; + + /* Declare the transmission with callback off. */ + cdc_acm -> ux_slave_class_cdc_acm_transmission_status = UX_FALSE; + } + else + + /* We should not try to stop an non existing transmission. */ + return(UX_ERROR); + + break; + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Function not supported. Return an error. */ + status = UX_FUNCTION_NOT_SUPPORTED; + } + + /* Return status to caller. */ + return(status); + +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_read.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_read.c new file mode 100644 index 0000000..2994e36 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_read.c @@ -0,0 +1,220 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the CDC class. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Address of cdc_acm class */ +/* instance */ +/* buffer Pointer to buffer to save */ +/* received data */ +/* requested_length Length of bytes to read */ +/* actual_length Pointer to save number of */ +/* bytes read */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_mutex_off Release mutex */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_read(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_TRANSFER *transfer_request; +UINT status= UX_SUCCESS; +ULONG local_requested_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ACM_READ, cdc_acm, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Check if current cdc-acm is using callback or not. We cannot use direct reads with callback on. */ + if (cdc_acm -> ux_slave_class_cdc_acm_transmission_status == UX_TRUE) + + /* Not allowed. */ + return(UX_ERROR); + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* This is the first time we are activated. We need the interface to the class. */ + interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if OUT we have the correct endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_OUT) + { + + /* So the next endpoint has to be the OUT endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* Protect this thread. */ + _ux_utility_mutex_on(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex); + + /* All CDC reading are on the endpoint OUT, from the host. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Reset the actual length. */ + *actual_length = 0; + + /* Check if we need more transactions. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && requested_length != 0) + { + + /* Check if we have enough in the local buffer. */ + if (requested_length > endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize) + + /* We have too much to transfer. */ + local_requested_length = endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize; + + else + + /* We can proceed with the demanded length. */ + local_requested_length = requested_length; + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, local_requested_length, local_requested_length); + + /* Check the status */ + if (status == UX_SUCCESS) + { + + /* We need to copy the buffer locally. */ + _ux_utility_memory_copy(buffer, transfer_request -> ux_slave_transfer_request_data_pointer, + transfer_request -> ux_slave_transfer_request_actual_length); + + /* Next buffer address. */ + buffer += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + *actual_length += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Decrement what left has to be done. */ + requested_length -= transfer_request -> ux_slave_transfer_request_actual_length; + + + /* Is this a short packet or a ZLP indicating we are done with this transfer ? */ + if (transfer_request -> ux_slave_transfer_request_actual_length < endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize) + { + + /* We are done. */ + /* Free Mutex resource. */ + _ux_utility_mutex_off(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex); + + /* Return with success. */ + return(UX_SUCCESS); + + } + } + else + { + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex); + + /* We got an error. */ + return(status); + } + } + + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex); + + /* Check why we got here, either completion or device was extracted. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Device must have been extracted. */ + return (UX_TRANSFER_NO_ANSWER); + } + else + + /* Simply return the last transaction result. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c new file mode 100644 index 0000000..e73e162 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_unitialize.c @@ -0,0 +1,100 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_uninitialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function uninitialize the cdc-acm class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_mutex_delete Delete Mutex */ +/* _ux_utility_memory_free Free used local memory */ +/* */ +/* CALLED BY */ +/* */ +/* CDC Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_uninitialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_CDC_ACM *cdc_acm; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + cdc_acm = (UX_SLAVE_CLASS_CDC_ACM *) class -> ux_slave_class_instance; + + /* Sanity check. */ + if (cdc_acm != UX_NULL) + { + + /* Delete the IN endpoint mutex. */ + _ux_utility_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex); + + /* Out Mutex. */ + _ux_utility_mutex_delete(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_out_mutex); + + /* Free the resources. */ + _ux_utility_memory_free(cdc_acm); + + } + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write.c new file mode 100644 index 0000000..0014a11 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write.c @@ -0,0 +1,227 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the CDC class. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Address of cdc_acm class */ +/* instance */ +/* buffer Pointer to data to write */ +/* requested_length Length of bytes to write */ +/* actual_length Pointer to save number of */ +/* bytes written */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_mutex_on Take Mutex */ +/* _ux_utility_mutex_off Release Mutex */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_write(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_DEVICE *device; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_TRANSFER *transfer_request; +ULONG local_requested_length; +UINT status = 0; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ACM_WRITE, cdc_acm, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Check if current cdc-acm is using callback or not. We cannot use direct reads with callback on. */ + if (cdc_acm -> ux_slave_class_cdc_acm_transmission_status == UX_TRUE) + + /* Not allowed. */ + return(UX_ERROR); + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* We need the interface to the class. */ + interface = cdc_acm -> ux_slave_class_cdc_acm_interface; + + /* Locate the endpoints. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* So the next endpoint has to be the IN endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* Protect this thread. */ + _ux_utility_mutex_on(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex); + + /* We are writing to the IN endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Reset the actual length. */ + *actual_length = 0; + + /* Check if the application forces a 0 length packet. */ + if (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && requested_length == 0) + { + + /* Send the request for 0 byte packet to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, 0, 0); + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex); + + /* Return the status. */ + return(status); + + + } + else + { + /* Check if we need more transactions. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED && requested_length != 0) + { + + /* Check if we have enough in the local buffer. */ + if (requested_length > UX_SLAVE_REQUEST_DATA_MAX_LENGTH) + + /* We have too much to transfer. */ + local_requested_length = UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + else + + /* We can proceed with the demanded length. */ + local_requested_length = requested_length; + + /* On a out, we copy the buffer to the caller. Not very efficient but it makes the API + easier. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + buffer, local_requested_length); + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, local_requested_length, local_requested_length); + + /* Check the status */ + if (status == UX_SUCCESS) + { + + /* Next buffer address. */ + buffer += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Set the length actually received. */ + *actual_length += transfer_request -> ux_slave_transfer_request_actual_length; + + /* Decrement what left has to be done. */ + requested_length -= transfer_request -> ux_slave_transfer_request_actual_length; + + } + + else + { + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex); + + /* We had an error, abort. */ + return(status); + } + } + } + + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&cdc_acm -> ux_slave_class_cdc_acm_endpoint_in_mutex); + + /* Check why we got here, either completion or device was extracted. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Device must have been extracted. */ + return (UX_TRANSFER_NO_ANSWER); + } + else + + /* Simply return the last transaction result. */ + return(status); + +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c new file mode 100644 index 0000000..15d4824 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_acm_write_with_callback.c @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_acm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_acm_write_with_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the CDC class with callback */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Address of cdc_acm class */ +/* instance */ +/* buffer Pointer to data to write */ +/* requested_length Length of bytes to write */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_acm_write_with_callback(UX_SLAVE_CLASS_CDC_ACM *cdc_acm, UCHAR *buffer, + ULONG requested_length) +{ + +UX_SLAVE_DEVICE *device; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ACM_WRITE, cdc_acm, buffer, requested_length, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* As long as the device is in the CONFIGURED state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Cannot proceed with command, the interface is down. */ + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Are we already in transmission mode ? */ + if (cdc_acm -> ux_slave_class_cdc_acm_transmission_status != UX_TRUE) + { + + /* We should not to that ! */ + return(UX_ERROR); + + } + + /* Have we already scheduled a buffer ? */ + if (cdc_acm -> ux_slave_class_cdc_acm_scheduled_write == UX_TRUE) + { + + /* We should not to that ! */ + return(UX_ERROR); + } + + /* Save the length to be sent. */ + cdc_acm -> ux_slave_class_cdc_acm_callback_total_length = requested_length; + + /* And the buffer pointer. */ + cdc_acm -> ux_slave_class_cdc_acm_callback_data_pointer = buffer; + + /* Schedule a transmission. */ + cdc_acm -> ux_slave_class_cdc_acm_scheduled_write = UX_TRUE; + + /* Invoke the bulkin thread by sending a flag . */ + status = _ux_utility_event_flags_set(&cdc_acm -> ux_slave_class_cdc_acm_event_flags_group, UX_DEVICE_CLASS_CDC_ACM_WRITE_EVENT, TX_OR); + + /* Simply return the last function result. When we leave this function, the deferred writing has been scheduled. */ + return(status); + +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_activate.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_activate.c new file mode 100644 index 0000000..eca34ed --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_activate.c @@ -0,0 +1,244 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_ecm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_ecm_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function activates the USB CDC_ECM device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to cdc_ecm command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_ecm_activate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_CDC_ECM *cdc_ecm; +UX_SLAVE_CLASS *class; +UX_SLAVE_ENDPOINT *endpoint; +ULONG physical_address_msw; +ULONG physical_address_lsw; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Check if this is the Control or Data interface. */ + if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_CDC_ECM_CLASS_COMMUNICATION_CONTROL) + { + + /* Store the class instance into the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)cdc_ecm; + + /* Now the opposite, store the interface in the class instance. */ + cdc_ecm -> ux_slave_class_cdc_ecm_interface = interface; + + /* Locate the interrupt endpoint. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Parse all endpoints. */ + while (endpoint != UX_NULL) + { + + /* Check the endpoint direction, and type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) + { + + /* Look at type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT) + { + + /* We have found the interrupt endpoint, save it. */ + cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_endpoint = endpoint; + + /* Reset the endpoint buffers. */ + _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + + /* Resume the interrupt endpoint threads. */ + _ux_utility_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); + + } + + } + + /* Next endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + } + else + + /* This is the DATA Class, only store the cdc_ecm instance in the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)cdc_ecm; + + /* Reset the CDC ECM alternate setting to 0. */ + cdc_ecm -> ux_slave_class_cdc_ecm_current_alternate_setting = 0; + + /* Check if this is the Control or Data interface. */ + if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_CDC_ECM_CLASS_COMMUNICATION_DATA) + { + + /* Reset endpoint instance pointers. */ + cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint = UX_NULL; + cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint = UX_NULL; + + /* Does the data class have bulk endpoint declared ? If yes we need to start link. + If not, the host will change the alternate setting at a later stage. */ + if (interface -> ux_slave_interface_descriptor.bNumEndpoints != 0) + { + + /* Locate the endpoints. Control and Bulk in/out for Data Interface. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Parse all endpoints. */ + while (endpoint != UX_NULL) + { + + /* Check the endpoint direction, and type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) + { + + /* Look at type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT) + + /* We have found the bulk in endpoint, save it. */ + cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint = endpoint; + + } + else + { + /* Look at type for out endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT) + + /* We have found the bulk out endpoint, save it. */ + cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint = endpoint; + } + + /* Next endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + + /* Now check if all endpoints have been found. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint == UX_NULL || cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint == UX_NULL) + + /* Not all endpoints have been found. Major error, do not proceed. */ + return(UX_ERROR); + + /* Declare the link to be up. That may need to change later to make it dependant on the + WAN/Wireless modem. */ + cdc_ecm -> ux_slave_class_cdc_ecm_link_state = UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP; + + /* Wake up the Interrupt thread and send a network notification to the host. */ + _ux_utility_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT, TX_OR); + + /* Reset the endpoint buffers. */ + _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + + /* Resume the endpoint threads. */ + _ux_utility_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); + _ux_utility_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); + + } + + /* Setup the physical address of this IP instance. */ + physical_address_msw = (ULONG)((cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[0] << 8) | (cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[1])); + physical_address_lsw = (ULONG)((cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[2] << 24) | (cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[3] << 16) | + (cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[4] << 8) | (cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id[5])); + + /* Register this interface to the NetX USB interface broker. */ + _ux_network_driver_activate((VOID *) cdc_ecm, _ux_device_class_cdc_ecm_write, + &cdc_ecm -> ux_slave_class_cdc_ecm_network_handle, + physical_address_msw, + physical_address_lsw); + + /* Check Link. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_link_state == UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP) + { + + /* Communicate the state with the network driver. */ + _ux_network_driver_link_up(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle); + + /* If there is an activate function call it. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate != UX_NULL) + + /* Invoke the application. */ + cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate(cdc_ecm); + } + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_ACTIVATE, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, cdc_ecm, 0, 0, 0) + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkin_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkin_thread.c new file mode 100644 index 0000000..d1ed308 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkin_thread.c @@ -0,0 +1,229 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_ecm.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_ecm_bulkin_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the cdc_ecm bulkin endpoint. The bulk*/ +/* IN endpoint is used when the device wants to write data to be sent */ +/* to the host. */ +/* */ +/* INPUT */ +/* */ +/* cdc_ecm_class Address of cdc_ecm class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_utility_event_flags_get Get event flags */ +/* _ux_utility_mutex_on Take mutex */ +/* _ux_utility_mutex_off Free mutex */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_cdc_ecm_bulkin_thread(ULONG cdc_ecm_class) +{ + +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_CDC_ECM *cdc_ecm; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; +ULONG actual_flags; +NX_PACKET *current_packet; +UCHAR *packet_header; +ULONG transfer_length; + + /* Cast properly the cdc_ecm instance. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_SLAVE_CLASS, cdc_ecm_class) + + /* Get the cdc_ecm instance from this class container. */ + cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class -> ux_slave_class_instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* This thread runs forever but can be suspended or resumed. */ + while (1) + { + + /* For as long we are configured. */ + while (1) + { + + /* Wait until either a new packet has been added to the xmit queue, + or until there has been a change in the device state (i.e. disconnection). */ + _ux_utility_event_flags_get(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, (UX_DEVICE_CLASS_CDC_ECM_NEW_BULKIN_EVENT | + UX_DEVICE_CLASS_CDC_ECM_NEW_DEVICE_STATE_CHANGE_EVENT), + TX_OR_CLEAR, &actual_flags, TX_WAIT_FOREVER); + + /* Check the completion code and the actual flags returned. */ + if ((actual_flags & UX_DEVICE_CLASS_CDC_ECM_NEW_DEVICE_STATE_CHANGE_EVENT) == 0) + { + + /* Get the transfer request for the bulk IN pipe. */ + transfer_request = &cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint -> ux_slave_endpoint_transfer_request; + + /* Parse all packets. */ + while (cdc_ecm -> ux_slave_class_cdc_ecm_xmit_queue != UX_NULL) + { + + /* Ensure no other threads are modifying the xmit queue. */ + _ux_utility_mutex_on(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex); + + /* Get the current packet in the list. */ + current_packet = cdc_ecm -> ux_slave_class_cdc_ecm_xmit_queue; + + /* Set the next packet (or a NULL value) as the head of the xmit queue. */ + cdc_ecm -> ux_slave_class_cdc_ecm_xmit_queue = current_packet -> nx_packet_queue_next; + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex); + + /* If the link is down no need to rearm a packet. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_link_state == UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP) + { + + /* Load the address of the current packet header at the physical header. */ + packet_header = current_packet -> nx_packet_prepend_ptr; + + /* Can the packet fit in the transfer requests data buffer? */ + if (current_packet -> nx_packet_length <= UX_SLAVE_REQUEST_DATA_MAX_LENGTH) + { + + /* Copy the packet in the transfer descriptor buffer. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, packet_header, current_packet -> nx_packet_length); + + /* Calculate the transfer length. */ + transfer_length = current_packet -> nx_packet_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_PACKET_TRANSMIT, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, transfer_length, UX_DEVICE_CLASS_CDC_ECM_ETHERNET_PACKET_SIZE); + + /* Check error code. */ + if (status != UX_SUCCESS) + { + + /* Is this not a transfer abort? (this is expected to happen) */ + if (status != UX_TRANSFER_BUS_RESET) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + } + } + } + else + { + + /* Packet is too large. */ + + /* Report error to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_BUFFER_OVERFLOW); + } + } + + /* Free the packet that was just sent. First do some housekeeping. */ + current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_DEVICE_CLASS_CDC_ECM_ETHERNET_SIZE; + current_packet -> nx_packet_length = current_packet -> nx_packet_length - UX_DEVICE_CLASS_CDC_ECM_ETHERNET_SIZE; + + /* And ask Netx to release it. */ + nx_packet_transmit_release(current_packet); + } + } + else + { + + /* We need to ensure nobody is adding to the queue, so get the mutex protection. */ + _ux_utility_mutex_on(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex); + + /* Since we got the mutex, we know no one is trying to modify the queue; we also know + no one can start modifying the queue since the link state is down, so we can just + release the mutex. */ + _ux_utility_mutex_off(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex); + + /* We get here when the link is down. All packets pending must be freed. */ + while (cdc_ecm -> ux_slave_class_cdc_ecm_xmit_queue != UX_NULL) + { + + /* Get the current packet in the list. */ + current_packet = cdc_ecm -> ux_slave_class_cdc_ecm_xmit_queue; + + /* Set the next packet (or a NULL value) as the head of the xmit queue. */ + cdc_ecm -> ux_slave_class_cdc_ecm_xmit_queue = current_packet -> nx_packet_queue_next; + + /* Free the packet. */ + current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_DEVICE_CLASS_CDC_ECM_ETHERNET_SIZE; + current_packet -> nx_packet_length = current_packet -> nx_packet_length - UX_DEVICE_CLASS_CDC_ECM_ETHERNET_SIZE; + + /* And ask Netx to release it. */ + nx_packet_transmit_release(current_packet); + } + + /* Was the change in the device state caused by a disconnection? */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* Yes. Break out of the loop and suspend ourselves, waiting for the next configuration. */ + break; + } + } + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module or when a change of alternate setting happens. */ + _ux_utility_thread_suspend(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); + } +} diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c new file mode 100644 index 0000000..958e7aa --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_bulkout_thread.c @@ -0,0 +1,178 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_ecm.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_ecm_bulkout_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the cdc_ecm bulk out endpoint. It */ +/* is waiting for the host to send data on the bulk out endpoint to */ +/* the device. */ +/* */ +/* INPUT */ +/* */ +/* cdc_ecm_class Address of cdc_ecm class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_utility_memory_copy Copy memory */ +/* nx_packet_allocate Allocate NetX packet */ +/* nx_packet_release Free NetX packet */ +/* _ux_utility_thread_suspend Suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_cdc_ecm_bulkout_thread(ULONG cdc_ecm_class) +{ + +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_CDC_ECM *cdc_ecm; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; +NX_PACKET *packet; +ULONG ip_given_length; + + /* Cast properly the cdc_ecm instance. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_SLAVE_CLASS, cdc_ecm_class) + + /* Get the cdc_ecm instance from this class container. */ + cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class -> ux_slave_class_instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* This thread runs forever but can be suspended or resumed. */ + while (1) + { + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* We can accept new reception. Get a NX Packet */ + status = nx_packet_allocate(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool, &packet, + NX_RECEIVE_PACKET, MS_TO_TICK(UX_DEVICE_CLASS_CDC_ECM_PACKET_POOL_WAIT)); + + if (status == NX_SUCCESS) + { + + /* Select the transfer request associated with BULK OUT endpoint. */ + transfer_request = &cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint -> ux_slave_endpoint_transfer_request; + + /* And length. */ + transfer_request -> ux_slave_transfer_request_requested_length = UX_DEVICE_CLASS_CDC_ECM_MAX_PACKET_LENGTH; + transfer_request -> ux_slave_transfer_request_actual_length = 0; + + /* Memorize this packet at the beginning of the queue. */ + cdc_ecm -> ux_slave_class_cdc_ecm_receive_queue = packet; + + /* Reset the queue pointer of this packet. */ + packet -> nx_packet_queue_next = UX_NULL; + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_CDC_ECM_MAX_PACKET_LENGTH, + UX_DEVICE_CLASS_CDC_ECM_MAX_PACKET_LENGTH); + + /* Check the completion code. */ + if (status == UX_SUCCESS) + { + + /* We only proceed with packets that are received OK, if error, ignore the packet. */ + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_PACKET_RECEIVE, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ + packet -> nx_packet_prepend_ptr += sizeof(USHORT); + + /* Set the prepend, length, and append fields. */ + packet -> nx_packet_length = transfer_request -> ux_slave_transfer_request_actual_length; + packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + transfer_request -> ux_slave_transfer_request_actual_length; + + /* Copy the received packet in the IP packet data area. */ + _ux_utility_memory_copy(packet -> nx_packet_prepend_ptr, transfer_request -> ux_slave_transfer_request_data_pointer, packet -> nx_packet_length); + + /* Calculate the accurate packet length from ip header. */ + if((*(packet -> nx_packet_prepend_ptr + 12) == 0x08) && + (*(packet -> nx_packet_prepend_ptr + 13) == 0)) + { + + ip_given_length = _ux_utility_short_get_big_endian(packet -> nx_packet_prepend_ptr + 16) + UX_DEVICE_CLASS_CDC_ECM_ETHERNET_SIZE; + packet -> nx_packet_length = ip_given_length ; + packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + ip_given_length; + } + + /* Send that packet to the NetX USB broker. */ + _ux_network_driver_packet_received(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle, packet); + } + else + + /* Free the packet that was not successfully received. */ + nx_packet_release(packet); + } + else + { + + /* Packet allocation timed out. Note that the timeout value is + configurable. */ + + /* Error trap. No need for trace, since NetX does it. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + } + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ + _ux_utility_thread_suspend(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_change.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_change.c new file mode 100644 index 0000000..4306003 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_change.c @@ -0,0 +1,200 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_ecm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_ecm_change PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function changes the interface of the CDC_ECM device */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to cdc_ecm command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_network_driver_link_up Link status up */ +/* _ux_network_driver_link_down Link status down */ +/* _ux_utility_memory_set Set memory */ +/* _ux_utility_thread_resume Resume thread */ +/* _ux_utility_event_flags_set Set event flags */ +/* _ux_device_stack_transfer_all_request_abort */ +/* Abort transfer */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_ecm_change(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_CDC_ECM *cdc_ecm; +UX_SLAVE_CLASS *class; +UX_SLAVE_ENDPOINT *endpoint; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Locate the endpoints. Control and Bulk in/out for Data Interface. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* If the interface to mount has a non zero alternate setting, the class is really active with + the endpoints active. If the interface reverts to alternate setting 0, it needs to have + the pending transactions terminated. */ + if (interface -> ux_slave_interface_descriptor.bAlternateSetting != 0) + { + + /* Parse all endpoints. */ + while (endpoint != UX_NULL) + { + + /* Check the endpoint direction, and type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) + { + + /* Look at type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT) + + /* We have found the bulk in endpoint, save it. */ + cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint = endpoint; + + } + else + { + /* Look at type for out endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT) + + /* We have found the bulk out endpoint, save it. */ + cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint = endpoint; + } + + /* Next endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* Now check if all endpoints have been found. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint == UX_NULL || cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint == UX_NULL) + + /* Not all endpoints have been found. Major error, do not proceed. */ + return(UX_ERROR); + + /* Declare the link to be up. */ + cdc_ecm -> ux_slave_class_cdc_ecm_link_state = UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP; + + /* Communicate the state with the network driver. */ + _ux_network_driver_link_up(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle); + + /* Reset the endpoint buffers. */ + _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + _ux_utility_memory_set(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + + /* Resume the endpoint threads. */ + _ux_utility_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); + _ux_utility_thread_resume(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); + + /* Wake up the Interrupt thread and send a network notification to the host. */ + _ux_utility_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT, TX_OR); + + /* If there is an activate function call it. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate != UX_NULL) + + /* Invoke the application. */ + cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate(cdc_ecm); + } + else + { + + /* In this case, we are reverting to the Alternate Setting 0. */ + + /* Declare the link to be down. */ + cdc_ecm -> ux_slave_class_cdc_ecm_link_state = UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_DOWN; + + /* Communicate the state with the network driver. */ + _ux_network_driver_link_down(cdc_ecm -> ux_slave_class_cdc_ecm_network_handle); + + /* Terminate the transactions pending on the bulk in endpoint. If there is a transfer on the + bulk out endpoint, we simply let it finish and let NetX throw it away. */ + _ux_device_stack_transfer_all_request_abort(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint, UX_TRANSFER_APPLICATION_RESET); + + /* Notify the thread waiting for network notification events. In this case, + the event is that the link state has been switched to down. */ + _ux_utility_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT, TX_OR); + + /* Wake up the bulk in thread so that it can clean up the xmit queue. */ + _ux_utility_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NEW_DEVICE_STATE_CHANGE_EVENT, TX_OR); + + /* If there is a deactivate function call it. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate != UX_NULL) + + /* Invoke the application. */ + cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate(cdc_ecm); + } + + /* Set the CDC ECM alternate setting to the new one. */ + cdc_ecm -> ux_slave_class_cdc_ecm_current_alternate_setting = interface -> ux_slave_interface_descriptor.bAlternateSetting; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_CHANGE, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, cdc_ecm, 0, 0, 0) + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_control_request.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_control_request.c new file mode 100644 index 0000000..f4b4ce2 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_control_request.c @@ -0,0 +1,127 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_ecm.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_ecm_control_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* cdc_ecm Pointer to cdc_ecm class */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_short_get Get 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* CDC_ECM Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_ecm_control_request(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +ULONG request; +ULONG request_value; +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_CDC_ECM *cdc_ecm; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the pointer to the transfer request associated with the control endpoint. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Extract all necessary fields of the request. */ + request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST); + request_value = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE); + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the cdc_ecm instance from this class container. */ + cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class -> ux_slave_class_instance; + + /* Here we proceed only the standard request we know of at the device level. */ + switch (request) + { + + case UX_DEVICE_CLASS_CDC_ECM_SET_ETHERNET_MULTICAST_FILTER : + + /* Save the multicast filter. */ + cdc_ecm -> ux_slave_class_cdc_ecm_ethernet_multicast_filter = request_value; + break ; + + case UX_DEVICE_CLASS_CDC_ECM_SET_ETHERNET_POWER_MANAGEMENT_FILTER : + + /* Save the power management filter. */ + cdc_ecm -> ux_slave_class_cdc_ecm_ethernet_power_management_filter = request_value; + break ; + + case UX_DEVICE_CLASS_CDC_ECM_SET_ETHERNET_PACKET_FILTER : + + /* Save the packet filter. */ + cdc_ecm -> ux_slave_class_cdc_ecm_ethernet_packet_filter = request_value; + break ; + + case UX_DEVICE_CLASS_CDC_ECM_GET_ETHERNET_POWER_MANAGEMENT_FILTER : + default: + + /* Unknown function. It's not handled. */ + return(UX_ERROR); + } + + /* It's handled. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_deactivate.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_deactivate.c new file mode 100644 index 0000000..30d5319 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_deactivate.c @@ -0,0 +1,158 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_ecm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_ecm_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivate an instance of the cdc_ecm class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_all_request_abort */ +/* Abort all transfers */ +/* _ux_utility_event_flags_set Set event flags */ +/* _ux_network_driver_deactivate Deactivate NetX USB interface */ +/* */ +/* CALLED BY */ +/* */ +/* CDC_ECM Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_ecm_deactivate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_CDC_ECM *cdc_ecm; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. Normally the interface can be derived + from the class instance but since CDC_ECM has 2 interfaces and we only store the Control + interface in the class container, we used the class_command pointer to retrieve the + correct interface which issued the deactivation. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Check if this is the Control or Data interface. We only need to dismount the link and abort the + transfer once for the 2 classes. */ + if (interface -> ux_slave_interface_descriptor.bInterfaceClass == UX_DEVICE_CLASS_CDC_ECM_CLASS_COMMUNICATION_CONTROL) + { + + /* Is the link state up? */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_link_state == UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP) + { + + /* Then we've found the bulk endpoints and started the threads. */ + + /* Abort transfers. Note that since the bulk out thread is most likely waiting for + a transfer from the host, this will allow it to resume and suspend itself. */ + _ux_device_stack_transfer_all_request_abort(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint, UX_TRANSFER_BUS_RESET); + _ux_device_stack_transfer_all_request_abort(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint, UX_TRANSFER_BUS_RESET); + + /* Declare the link to be down. That may need to change later to make it dependent on the + WAN/Wireless modem. */ + cdc_ecm -> ux_slave_class_cdc_ecm_link_state = UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_DOWN; + + /* Is there an interrupt endpoint? */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_endpoint != UX_NULL) + + /* Abort the transfers on the interrupt endpoint as well. */ + _ux_device_stack_transfer_all_request_abort(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_endpoint, UX_TRANSFER_BUS_RESET); + + /* Wake up the bulk in thread so it will release the NetX resources used and suspend. */ + _ux_utility_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NEW_DEVICE_STATE_CHANGE_EVENT, TX_OR); + + /* If there is a deactivate function call it. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate != UX_NULL) + + /* Invoke the application. */ + cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate(cdc_ecm); + + /* Deregister this interface to the NetX USB interface broker. */ + _ux_network_driver_deactivate((VOID *) cdc_ecm, cdc_ecm -> ux_slave_class_cdc_ecm_network_handle); + } + else + { + + /* The link state is down. */ + + /* Did activation succeed? */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_endpoint != UX_NULL && cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_endpoint != UX_NULL) + { + + /* The only thing we need to do is deregister this interface to the NetX USB interface broker. */ + _ux_network_driver_deactivate((VOID *) cdc_ecm, cdc_ecm -> ux_slave_class_cdc_ecm_network_handle); + } + else + { + + /* Activation did not succeed. Nothing to do. */ + } + } + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_CDC_ECM_DEACTIVATE, cdc_ecm, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(cdc_ecm); + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_entry.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_entry.c new file mode 100644 index 0000000..802aaaa --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_entry.c @@ -0,0 +1,161 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_ecm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_class_device_cdc_ecm_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the cdc_ecm class. It */ +/* will be called by the device stack enumeration module when the */ +/* host has sent a SET_CONFIGURATION command and the cdc_ecm interface */ +/* needs to be mounted. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_cdc_ecm_initialize Initialize cdc_ecm class */ +/* _ux_device_class_cdc_ecm_uninitialize Uninitialize cdc_ecm class*/ +/* _ux_device_class_cdc_ecm_activate Activate cdc_ecm class */ +/* _ux_device_class_cdc_ecm_deactivate Deactivate cdc_ecm class */ +/* _ux_device_class_cdc_ecm_change Alternate setting change */ +/* _ux_device_class_cdc_ecm_control_request Request control */ +/* */ +/* CALLED BY */ +/* */ +/* CDC_ECM Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_ecm_entry(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_slave_class_command_request) + { + + case UX_SLAVE_CLASS_COMMAND_INITIALIZE: + + /* Call the init function of the CDC_ECM class. */ + status = _ux_device_class_cdc_ecm_initialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_UNINITIALIZE: + + /* Call the init function of the CDC_ECM class. */ + status = _ux_device_class_cdc_ecm_uninitialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_QUERY: + + /* Check the CLASS definition in the interface descriptor. */ + if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_CDC_ECM_CLASS_COMMUNICATION_CONTROL || + command -> ux_slave_class_command_class == UX_DEVICE_CLASS_CDC_ECM_CLASS_COMMUNICATION_DATA) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_SLAVE_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the host has sent a SET_CONFIGURATION command + and this interface has to be mounted. In CDC ECM, the alternate setting 0 has no endpoints. + Only the Alternate Setting 1 has the Bulk IN and OUT endpoints active. */ + status = _ux_device_class_cdc_ecm_activate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_CHANGE: + + /* The change command is used when the host has sent a SET_INTERFACE command + to go from Alternate Setting 0 to 1 or revert to the default mode. */ + status = _ux_device_class_cdc_ecm_change(command); + + /* Return the completion status. */ + return(status); + + + case UX_SLAVE_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted. + The device endpoints have to be dismounted and the cdc_ecm thread canceled. */ + status = _ux_device_class_cdc_ecm_deactivate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_REQUEST: + + /* The request command is used when the host sends a command on the control endpoint. */ + status = _ux_device_class_cdc_ecm_control_request(command); + + /* Return the completion status. */ + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c new file mode 100644 index 0000000..b446066 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_initialize.c @@ -0,0 +1,266 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_ecm.h" +#include "ux_device_stack.h" + +UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_ecm_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB CDC_ECM device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to cdc_ecm command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_mutex_create Create Mutex */ +/* _ux_utility_mutex_delete Delete Mutex */ +/* _ux_utility_event_flags_create Create Flag group */ +/* _ux_utility_event_flags_delete Delete Flag group */ +/* _ux_utility_thread_create Create Thread */ +/* _ux_utility_thread_delete Delete Thread */ +/* nx_packet_pool_create Create NetX packet pool */ +/* nx_packet_pool_delete Delete NetX packet pool */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_ecm_initialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_CDC_ECM *cdc_ecm; +UX_SLAVE_CLASS_CDC_ECM_PARAMETER *cdc_ecm_parameter; +UX_SLAVE_CLASS *class; +UINT status; + + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Create an instance of the device cdc_ecm class. */ + cdc_ecm = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_CDC_ECM)); + + /* Check for successful allocation. */ + if (cdc_ecm == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Create a mutex to protect the CDC_ECM thread and the application messing up the transmit queue. */ + status = _ux_utility_mutex_create(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex, "ux_slave_class_cdc_ecm_mutex"); + if (status != UX_SUCCESS) + { + _ux_utility_memory_free(cdc_ecm); + return(UX_MUTEX_ERROR); + } + + /* Assume good result. */ + status = UX_SUCCESS; + + /* Allocate some memory for the bulk out thread stack. */ + cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + + /* Allocate some memory for the interrupt thread stack. */ + if (status == UX_SUCCESS) + { + cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + } + + /* Allocate some memory for the bulk in thread stack. */ + if (status == UX_SUCCESS) + { + cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + } + + /* Allocate some packet pool for reception. */ + if (status == UX_SUCCESS) + { + + /* UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE overflow has been checked by + * UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT outside of function. + */ + cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE); + + /* Check for successful allocation. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + else + { + /* Create a packet pool. */ + status = nx_packet_pool_create(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool, "CDC ECM Device Packet Pool", + UX_DEVICE_CLASS_CDC_ECM_NX_PAYLOAD_SIZE, cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory, + UX_DEVICE_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE); + } + } + + /* Interrupt endpoint treatment needs to be running in a different thread. So start + a new thread. We pass a pointer to the cdc_ecm instance to the new thread. This thread + does not start until we have a instance of the class. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread , "ux_slave_class_cdc_ecm_interrupt_thread", + _ux_device_class_cdc_ecm_interrupt_thread, + (ULONG) (ALIGN_TYPE) class, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack , + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_DONT_START); + if (status != UX_SUCCESS) + status = (UX_THREAD_ERROR); + } + + UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread), class) + + /* Check the creation of this thread. */ + if (status == UX_SUCCESS) + { + + /* Bulk endpoint treatment needs to be running in a different thread. So start + a new thread. We pass a pointer to the cdc_ecm instance to the new thread. This thread + does not start until we have a instance of the class. */ + status = _ux_utility_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread , "ux_slave_class_cdc_ecm_bulkout_thread", + _ux_device_class_cdc_ecm_bulkout_thread, + (ULONG) (ALIGN_TYPE) class, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack , + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_DONT_START); + if (status != UX_SUCCESS) + status = (UX_THREAD_ERROR); + else + { + + UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread), class) + + /* Bulk endpoint treatment needs to be running in a different thread. So start + a new thread. We pass a pointer to the cdc_ecm instance to the new thread. This thread + does not start until we have a instance of the class. */ + status = _ux_utility_thread_create(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread , "ux_slave_class_cdc_ecm_bulkin_thread", + _ux_device_class_cdc_ecm_bulkin_thread, + (ULONG) (ALIGN_TYPE) class, (VOID *) cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack , + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_DONT_START); + if (status != UX_SUCCESS) + status = (UX_THREAD_ERROR); + else + { + + UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread), class) + + /* Create a event flag group for the cdc_ecm class to synchronize with the event interrupt thread. */ + status = _ux_utility_event_flags_create(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, "ux_device_class_cdc_ecm_event_flag"); + if (status != UX_SUCCESS) + status = (UX_EVENT_ERROR); + else + { + + /* Save the address of the CDC_ECM instance inside the CDC_ECM container. */ + class -> ux_slave_class_instance = (VOID *) cdc_ecm; + + /* Get the pointer to the application parameters for the cdc_ecm class. */ + cdc_ecm_parameter = command -> ux_slave_class_command_parameter; + + /* Store the start and stop signals if needed by the application. */ + cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_activate = cdc_ecm_parameter -> ux_slave_class_cdc_ecm_instance_activate; + cdc_ecm -> ux_slave_class_cdc_ecm_parameter.ux_slave_class_cdc_ecm_instance_deactivate = cdc_ecm_parameter -> ux_slave_class_cdc_ecm_instance_deactivate; + + /* Copy the local node ID. */ + _ux_utility_memory_copy(cdc_ecm -> ux_slave_class_cdc_ecm_local_node_id, cdc_ecm_parameter -> ux_slave_class_cdc_ecm_parameter_local_node_id, + UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH); + + /* Copy the remote node ID. */ + _ux_utility_memory_copy(cdc_ecm -> ux_slave_class_cdc_ecm_remote_node_id, cdc_ecm_parameter -> ux_slave_class_cdc_ecm_parameter_remote_node_id, + UX_DEVICE_CLASS_CDC_ECM_NODE_ID_LENGTH); + + /* Store the rest of the parameters as they are in the local instance. */ + _ux_utility_memory_copy(&cdc_ecm -> ux_slave_class_cdc_ecm_parameter, cdc_ecm_parameter, sizeof (UX_SLAVE_CLASS_CDC_ECM_PARAMETER)); + + return(UX_SUCCESS); + } + + _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); + } + + _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); + } + + _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); + } + + /* Free allocated resources. */ + + if (cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool.nx_packet_pool_id) + nx_packet_pool_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool); + if (cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory) + _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory); + if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack) + _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack); + if (cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack) + _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack); + if (cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack) + _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack); + _ux_utility_mutex_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex); + _ux_utility_memory_free(cdc_ecm); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_interrupt_thread.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_interrupt_thread.c new file mode 100644 index 0000000..8ca7bb8 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_interrupt_thread.c @@ -0,0 +1,152 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_ecm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_ecm_interrupt_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the cdc_ecm interrupt endpoint */ +/* */ +/* INPUT */ +/* */ +/* cdc_ecm_class Address of cdc_ecm class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_utility_event_flags_get Get event flags */ +/* _ux_utility_short_put Put 16-bit value to buffer */ +/* _ux_utility_thread_suspend Suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_cdc_ecm_interrupt_thread(ULONG cdc_ecm_class) +{ + +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_CDC_ECM *cdc_ecm; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; +ULONG actual_flags; +UCHAR *notification_buffer; + + /* Cast properly the cdc_ecm instance. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_SLAVE_CLASS, cdc_ecm_class) + + /* Get the cdc_ecm instance from this class container. */ + cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class -> ux_slave_class_instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + + /* All CDC_ECM events are on the interrupt endpoint IN, from the host. */ + transfer_request = &cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_endpoint -> ux_slave_endpoint_transfer_request; + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + + /* Wait until we have a event sent by the application. We do not treat yet the case where a timeout based + on the interrupt pipe frequency or a change in the idle state forces us to send an empty report. */ + _ux_utility_event_flags_get(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, + UX_DEVICE_CLASS_CDC_ECM_NETWORK_NOTIFICATION_EVENT, + TX_OR_CLEAR, &actual_flags, TX_WAIT_FOREVER); + + /* Build the Network Notification response. */ + notification_buffer = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Set the request type. */ + *(notification_buffer + UX_SETUP_REQUEST_TYPE) = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + + /* Set the request itself. */ + *(notification_buffer + UX_SETUP_REQUEST) = 0; + + /* Set the value. It is the network link. */ + _ux_utility_short_put(notification_buffer + UX_SETUP_VALUE, (USHORT)(cdc_ecm -> ux_slave_class_cdc_ecm_link_state)); + + /* Set the Index. It is interface. The interface used is the DATA interface. Here we simply take the interface number of the CONTROL and add 1 to it + as it is assumed the classes are contiguous in number. */ + _ux_utility_short_put(notification_buffer + UX_SETUP_INDEX, (USHORT)(cdc_ecm -> ux_slave_class_cdc_ecm_interface -> ux_slave_interface_descriptor.bInterfaceNumber + 1)); + + /* And the length is zero. */ + *(notification_buffer + UX_SETUP_LENGTH) = 0; + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_CDC_ECM_INTERRUPT_RESPONSE_LENGTH, + UX_DEVICE_CLASS_CDC_ECM_INTERRUPT_RESPONSE_LENGTH); + + /* Check error code. */ + if (status != UX_SUCCESS) + { + + /* Since bus resets are expected, we do not treat it as an error. */ + if (status != UX_TRANSFER_BUS_RESET) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + } + } + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ + _ux_utility_thread_suspend(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_uninitialize.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_uninitialize.c new file mode 100644 index 0000000..217b92b --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_uninitialize.c @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC-ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_ecm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_ecm_uninitialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deinitializes the resources for the specified CDC-ECM */ +/* instance. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to storage command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_mutex_delete Delete mutex */ +/* _ux_utility_thread_delete Delete thread */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_event_flags_delete Delete event flags */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Device CDC-ECM Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_ecm_uninitialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_CDC_ECM *cdc_ecm; +UX_SLAVE_CLASS *class; + + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) class -> ux_slave_class_instance; + + /* Sanity check. */ + if (cdc_ecm != UX_NULL) + { + + /* Deinitialize resources. We do not check if they have been allocated + because if they weren't, the class register (called by the application) + would have failed. */ + + /* Delete the xmit queue mutex. */ + _ux_utility_mutex_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex); + + /* Delete bulk out thread . */ + _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread); + + /* Free bulk out thread stack. */ + _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkout_thread_stack); + + /* Delete interrupt thread. */ + _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread); + + /* Free interrupt thread stack. */ + _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_interrupt_thread_stack); + + /* Delete bulk in thread. */ + _ux_utility_thread_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread); + + /* Free bulk in thread stack. */ + _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_bulkin_thread_stack); + + /* Delete the interrupt thread sync event flags group. */ + _ux_utility_event_flags_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group); + + /* Delete the reception packet pool. */ + nx_packet_pool_delete(&cdc_ecm -> ux_slave_class_cdc_ecm_packet_pool); + + /* Free the packet pool memory. */ + _ux_utility_memory_free(cdc_ecm -> ux_slave_class_cdc_ecm_pool_memory); + + /* Free the resources. */ + _ux_utility_memory_free(cdc_ecm); + } + + /* Return completion status. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_cdc_ecm_write.c b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_write.c new file mode 100644 index 0000000..4e2293a --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_cdc_ecm_write.c @@ -0,0 +1,130 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_cdc_ecm.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_cdc_ecm_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a packet into a queue for later thread */ +/* processing. */ +/* */ +/* INPUT */ +/* */ +/* cdc_ecm Address of cdc_ecm class */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_mutex_off Release mutex */ +/* _ux_utility_event_flags_set Set event flags */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_cdc_ecm_write(VOID *cdc_ecm_class, NX_PACKET *packet) +{ + +UINT status; +UX_SLAVE_CLASS_CDC_ECM *cdc_ecm; + + /* Proper class casting. */ + cdc_ecm = (UX_SLAVE_CLASS_CDC_ECM *) cdc_ecm_class; + + /* Protect this thread. */ + _ux_utility_mutex_on(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex); + + /* We only want to send the packet if the link is up. */ + if (cdc_ecm->ux_slave_class_cdc_ecm_link_state == UX_DEVICE_CLASS_CDC_ECM_LINK_STATE_UP) + { + + /* Check the queue. See if there is something that is being sent. */ + if (cdc_ecm -> ux_slave_class_cdc_ecm_xmit_queue == UX_NULL) + + /* Memorize this packet at the beginning of the queue. */ + cdc_ecm -> ux_slave_class_cdc_ecm_xmit_queue = packet; + + else + + /* Add the packet to the end of the queue. */ + cdc_ecm -> ux_slave_class_cdc_ecm_xmit_queue_tail -> nx_packet_queue_next = packet; + + /* Set the tail. */ + cdc_ecm -> ux_slave_class_cdc_ecm_xmit_queue_tail = packet; + + /* The packet to be sent is the last in the chain. */ + packet -> nx_packet_queue_next = NX_NULL; + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex); + + /* Set an event to wake up the bulkin thread. */ + _ux_utility_event_flags_set(&cdc_ecm -> ux_slave_class_cdc_ecm_event_flags_group, UX_DEVICE_CLASS_CDC_ECM_NEW_BULKIN_EVENT, TX_OR); + + /* Packet successfully added. Return success. */ + status = UX_SUCCESS; + } + else + { + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&cdc_ecm -> ux_slave_class_cdc_ecm_mutex); + + /* Report error to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_CDC_ECM_LINK_STATE_DOWN_ERROR); + + /* Return error. */ + status = UX_ERROR; + } + + /* We are done here. */ + return(status); +} diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_activate.c b/common/usbx_device_classes/src/ux_device_class_dfu_activate.c new file mode 100644 index 0000000..1ac1c50 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_dfu_activate.c @@ -0,0 +1,150 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device DFU Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dfu.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dfu_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB DFU device. */ +/* This class can be activated either as part of the device primary */ +/* framework or after a PORT_RESET detected. */ +/* This is detected through the protocol field. If 1, we are in the */ +/* device regular mode. If 2, we are activated through the DFU */ +/* mode. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to dfu command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_thread_resume Resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dfu_activate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_DFU *dfu; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + dfu = (UX_SLAVE_CLASS_DFU *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Store the class instance into the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)dfu; + + /* Now the opposite, store the interface in the class instance. */ + dfu -> ux_slave_class_dfu_interface = interface; + + /* Check the protocol activation field to determine in which state of the DFU class + we are. */ + switch (command -> ux_slave_class_command_protocol) + { + + case UX_SLAVE_CLASS_DFU_PROTOCOL_RUNTIME : + + /* In the system, state the DFU state machine to application idle. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_APP_IDLE; + + /* Set the mode to Runtime. */ + _ux_system_slave -> ux_system_slave_device_dfu_mode = UX_DEVICE_CLASS_DFU_MODE_RUNTIME ; + + break; + + + case UX_SLAVE_CLASS_DFU_PROTOCOL_DFU_MODE : + + /* In the system, state the DFU state machine to DFU idle. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_IDLE; + + /* Reset the download/upload parameters. */ + dfu -> ux_slave_class_dfu_download_block_count = 0; + dfu -> ux_slave_class_dfu_upload_block_count = 0; + + /* Set the mode to DFU mode. */ + _ux_system_slave -> ux_system_slave_device_dfu_mode = UX_DEVICE_CLASS_DFU_MODE_DFU ; + + break; + + default : + + /* We should never get here. */ + return(UX_ERROR); + + } + + + /* If there is a activate function call it. */ + if (dfu -> ux_slave_class_dfu_instance_activate != UX_NULL) + { + /* Invoke the application. */ + dfu -> ux_slave_class_dfu_instance_activate(dfu); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DFU_ACTIVATE, dfu, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, dfu, 0, 0, 0) + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_control_request.c b/common/usbx_device_classes/src/ux_device_class_dfu_control_request.c new file mode 100644 index 0000000..ff5b8db --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_dfu_control_request.c @@ -0,0 +1,635 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device DFU Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dfu.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dfu_control_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* dfu Pointer to dfu class */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_endpoint_stall Endpoint stall */ +/* _ux_device_stack_transfer_request Transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* DFU Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dfu_control_request(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_DFU *dfu; + +ULONG request; +ULONG request_length; +ULONG actual_length; +ULONG media_status; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the storage instance from this class container. */ + dfu = (UX_SLAVE_CLASS_DFU *) class -> ux_slave_class_instance; + + /* Get the pointer to the transfer request associated with the control endpoint. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Extract all necessary fields of the request. */ + request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST); + + /* Pickup the request length. */ + request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH); + + /* What state are we in ? */ + switch (_ux_system_slave -> ux_system_slave_device_dfu_state_machine) + { + + case UX_SYSTEM_DFU_STATE_APP_IDLE : + + + /* Here we process only the request we can accept in the APP IDLE state. */ + switch (request) + { + + case UX_SLAVE_CLASS_DFU_COMMAND_DETACH : + + /* The host is asking for a Detach and switch to the DFU mode. Either we force the reset here or + we wait for a specified timer. If there is no reset while this timer is running we abandon + the DFU Detach.*/ + if (_ux_system_slave -> ux_system_slave_device_dfu_capabilities & UX_SLAVE_CLASS_DFU_CAPABILITY_WILL_DETACH) + { + + /* Wake up the DFU thread and send a detach request.. */ + _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT, TX_OR); + + } + else + { + + /* We expect the host to issue a reset. Arm a timer in the DFU thread. */ + _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET, TX_OR); + + } + + /* We can switch dfu state machine. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_APP_DETACH; + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : + + /* Fill the status data payload. First with status. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + + /* Poll time out value is set to 1ms. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + + /* Next state. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* String index set to 0. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : + + /* Fill the status data payload. First with state. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); + + break; + + default: + + /* Unknown function. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + break; + } + + break; + + case UX_SYSTEM_DFU_STATE_APP_DETACH : + + /* Here we process only the request we can accept in the APP DETACH state. */ + switch (request) + { + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : + + /* Fill the status data payload. First with status. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + + /* Poll time out value is set to 1ms. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + + /* Next state. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* String index set to 0. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : + + /* Fill the status data payload. First with state. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); + + break; + + default: + + /* Unknown function. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + break; + } + + break; + + case UX_SYSTEM_DFU_STATE_DFU_IDLE : + + /* Here we process only the request we can accept in the DFU mode IDLE state. */ + switch (request) + { + + case UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD : + + /* We received a DOWNLOAD command. Check the length field of the request. It cannot be 0. */ + if (request_length == 0) + { + + /* Zero length download is not accepted. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + + /* In the system, state the DFU state machine to dfu ERROR. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_ERROR; + + } + else + { + + /* Have we declared a DOWNLOAD possible in our device framework ? */ + if (_ux_system_slave -> ux_system_slave_device_dfu_capabilities & UX_SLAVE_CLASS_DFU_CAPABILITY_CAN_DOWNLOAD) + { + + /* Send a notification to the application. Begin of transfer. */ + dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_BEGIN_DOWNLOAD); + + /* Write the first block to the firmware. */ + dfu -> ux_slave_class_dfu_write(dfu, dfu -> ux_slave_class_dfu_download_block_count, + transfer_request -> ux_slave_transfer_request_data_pointer, + request_length, + &actual_length); + + /* In the system, state the DFU state machine to dfu DOWNLOAD SYNC. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_DNLOAD_SYNC; + + /* Increase the block count. */ + dfu -> ux_slave_class_dfu_download_block_count++; + + } + else + { + + /* Download is not accepted. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + + /* In the system, state the DFU state machine to dfu ERROR. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_ERROR; + + } + + } + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_ABORT : + + /* Send a notification to the application. */ + dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_DOWNLOAD); + + /* In the system, state the DFU state machine to dfu IDLE. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_IDLE; + + /* Reset the download/upload parameters. */ + dfu -> ux_slave_class_dfu_download_block_count = 0; + dfu -> ux_slave_class_dfu_upload_block_count = 0; + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : + + /* Fill the status data payload. First with status. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + + /* Poll time out value is set to 1ms. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + + /* Next state. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) UX_SYSTEM_DFU_STATE_DFU_IDLE; + + /* String index set to 0. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : + + /* Fill the status data payload. First with state. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); + + break; + + default: + + /* Unknown function. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + + /* In the system, state the DFU state machine to dfu ERROR. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_ERROR; + + break; + } + + break; + + + case UX_SYSTEM_DFU_STATE_DFU_DNLOAD_SYNC : + + /* Here we process only the request we can accept in the DFU mode DOWNLOAD state. */ + switch (request) + { + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : + + /* Check if the device is still buys performing the write. Write could be delayed. */ + dfu -> ux_slave_class_dfu_get_status(dfu, &media_status); + + /* Check status of device. */ + switch (media_status) + { + + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK : + + /* Set the next state for idle and no error status. */ + dfu -> ux_slave_class_dfu_status = UX_SLAVE_CLASS_DFU_STATUS_OK ; + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNLOAD_IDLE; + break; + + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_BUSY : + + /* Set the next state for busy but no error status. */ + dfu -> ux_slave_class_dfu_status = UX_SLAVE_CLASS_DFU_STATUS_OK ; + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNBUSY; + break; + + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_ERROR : + + /* Set the next state for busy and error status. */ + dfu -> ux_slave_class_dfu_status = UX_SLAVE_CLASS_DFU_STATUS_ERROR_WRITE ; + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_ERROR; + break; + + } + + /* Fill the status data payload. First with status. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + + /* Poll time out value is set to 1ms. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + + /* Next state. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* String index set to 0. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : + + /* Fill the status data payload. First with state. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); + + break; + + default: + + /* Unknown function. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + + /* In the system, state the DFU state machine to dfu ERROR. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_ERROR; + + break; + } + + break; + + case UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_DNLOAD_IDLE : + + /* Here we process only the request we can accept in the DFU mode DNLOAD state. */ + switch (request) + { + + case UX_SLAVE_CLASS_DFU_COMMAND_DOWNLOAD : + + /* We received a DOWNLOAD command. Check the length field of the request. If it is 0, + we are done with the transfer. */ + if (request_length == 0) + { + + /* Send the notification of end of download to application. */ + dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_END_DOWNLOAD); + + /* In the system, state the DFU state machine to DFU MANIFEST SYNCH. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_SYNC; + + } + + else + { + + /* Write the next block to the firmware. */ + dfu -> ux_slave_class_dfu_write(dfu, dfu -> ux_slave_class_dfu_download_block_count, + transfer_request -> ux_slave_transfer_request_data_pointer, + request_length, + &actual_length); + + /* In the system, state the DFU state machine to dfu DOWNLOAD SYNC. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_DNLOAD_SYNC; + + /* Increase the block count. */ + dfu -> ux_slave_class_dfu_download_block_count++; + + } + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_ABORT : + + /* Send a notification to the application. */ + dfu -> ux_slave_class_dfu_notify(dfu, UX_SLAVE_CLASS_DFU_NOTIFICATION_ABORT_DOWNLOAD); + + /* In the system, state the DFU state machine to dfu IDLE. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_IDLE; + + /* Reset the download/upload parameters. */ + dfu -> ux_slave_class_dfu_download_block_count = 0; + dfu -> ux_slave_class_dfu_upload_block_count = 0; + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : + + /* Fill the status data payload. First with status. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + + /* Poll time out value is set to 1ms. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + + /* Next state. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* String index set to 0. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : + + /* Fill the status data payload. First with state. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); + + break; + + default: + + /* Unknown function. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + + /* In the system, state the DFU state machine to dfu ERROR. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_ERROR; + + break; + } + + break; + + case UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_SYNC : + + /* Here we process only the request we can accept in the MANIFEST SYNCH state. */ + switch (request) + { + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATUS : + + /* Check if the device is still buys performing the write. Write could be delayed. */ + dfu -> ux_slave_class_dfu_get_status(dfu, &media_status); + + /* Check status of device. */ + switch (media_status) + { + + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_OK : + + /* Set the next state for wait reset and no error status. */ + dfu -> ux_slave_class_dfu_status = UX_SLAVE_CLASS_DFU_STATUS_OK ; + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST_WAIT_RESET; + + /* Check who is responsible for the RESET. */ + if (_ux_system_slave -> ux_system_slave_device_dfu_capabilities & UX_SLAVE_CLASS_DFU_CAPABILITY_WILL_DETACH) + { + + /* Wake up the DFU thread and send a detach request.. */ + _ux_utility_event_flags_set(&dfu -> ux_slave_class_dfu_event_flags_group, UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT, TX_OR); + + } + + break; + + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_BUSY : + + /* Set the next state for busy but no error status. */ + dfu -> ux_slave_class_dfu_status = UX_SLAVE_CLASS_DFU_STATUS_OK ; + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_MANIFEST; + break; + + case UX_SLAVE_CLASS_DFU_MEDIA_STATUS_ERROR : + + /* Set the next state for busy and error status. */ + dfu -> ux_slave_class_dfu_status = UX_SLAVE_CLASS_DFU_STATUS_ERROR_WRITE ; + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_ERROR; + break; + } + + /* Fill the status data payload. First with status. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) dfu -> ux_slave_class_dfu_status; + + /* Poll time out value is set to 1ms. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT) = 1; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 1) = 0; + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_POLL_TIMEOUT + 2) = 0; + + /* Next state. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STATE) = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* String index set to 0. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_DFU_GET_STATUS_STRING) = 0; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATUS_LENGTH); + + break; + + case UX_SLAVE_CLASS_DFU_COMMAND_GET_STATE : + + /* Fill the status data payload. First with state. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR) _ux_system_slave -> ux_system_slave_device_dfu_state_machine; + + /* We have a request to obtain the status of the DFU instance. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH, UX_SLAVE_CLASS_DFU_GET_STATE_LENGTH); + + break; + + default: + + /* Unknown function. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + break; + } + + break; + + case UX_SLAVE_CLASS_DFU_STATUS_STATE_DFU_ERROR : + + /* Here we process only the request we can accept in the ERROR state. */ + switch (request) + { + + case UX_SLAVE_CLASS_DFU_COMMAND_CLEAR_STATUS : + + /* In the system, state the DFU state machine to dfu IDLE. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_DFU_IDLE; + + break; + + default: + + /* Unknown function. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + break; + + } + + break; + + + default: + + /* Unknown state. Should not happen. */ + return(UX_ERROR); + } + + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_deactivate.c b/common/usbx_device_classes/src/ux_device_class_dfu_deactivate.c new file mode 100644 index 0000000..f43f0a1 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_dfu_deactivate.c @@ -0,0 +1,127 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device DFU Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dfu.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dfu_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivate an instance of the dfu class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_all_request_abort Abort all transfers */ +/* */ +/* CALLED BY */ +/* */ +/* DFU Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dfu_deactivate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_DFU *dfu; +UX_SLAVE_ENDPOINT *endpoint_in; +UX_SLAVE_ENDPOINT *endpoint_out; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + dfu = (UX_SLAVE_CLASS_DFU *) class -> ux_slave_class_instance; + + /* We need the interface to the class. */ + interface = dfu -> ux_slave_class_dfu_interface; + + /* Locate the endpoints. */ + endpoint_in = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint_in -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* Wrong direction, we found the OUT endpoint first. */ + endpoint_out = endpoint_in; + + /* So the next endpoint has to be the IN endpoint. */ + endpoint_in = endpoint_out -> ux_slave_endpoint_next_endpoint; + } + else + { + + /* We found the endpoint IN first, so next endpoint is OUT. */ + endpoint_out = endpoint_in -> ux_slave_endpoint_next_endpoint; + } + + /* Terminate the transactions pending on the endpoints. */ + _ux_device_stack_transfer_all_request_abort(endpoint_in, UX_TRANSFER_BUS_RESET); + _ux_device_stack_transfer_all_request_abort(endpoint_out, UX_TRANSFER_BUS_RESET); + + /* If there is a deactivate function call it. */ + if (dfu -> ux_slave_class_dfu_instance_deactivate != UX_NULL) + { + /* Invoke the application. */ + dfu -> ux_slave_class_dfu_instance_deactivate(dfu); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_DFU_DEACTIVATE, dfu, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(dfu); + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_entry.c b/common/usbx_device_classes/src/ux_device_class_dfu_entry.c new file mode 100644 index 0000000..9e76da3 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_dfu_entry.c @@ -0,0 +1,139 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device DFU Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dfu.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_class_device_dfu_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the dfu class. It */ +/* will be called by the device stack enumeration module when the */ +/* host has sent a SET_CONFIGURATION command and the dfu interface */ +/* needs to be mounted. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_dfu_initialize Initialize dfu class */ +/* _ux_device_class_dfu_activate Activate dfu class */ +/* _ux_device_class_dfu_deactivate Deactivate dfu class */ +/* _ux_device_class_dfu_control_request Request control */ +/* */ +/* CALLED BY */ +/* */ +/* DFU Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dfu_entry(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_slave_class_command_request) + { + + case UX_SLAVE_CLASS_COMMAND_INITIALIZE: + + /* Call the init function of the DFU ACM class. */ + status = _ux_device_class_dfu_initialize(command); + + /* Return the completion status. */ + return(status); + + + case UX_SLAVE_CLASS_COMMAND_QUERY: + + /* Check the CLASS definition in the interface descriptor. */ + if (command -> ux_slave_class_command_class == UX_SLAVE_CLASS_DFU_CLASS) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_SLAVE_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the host has sent a SET_CONFIGURATION command + and this interface has to be mounted. Both Bulk endpoints have to be mounted + and the dfu thread needs to be activated. */ + status = _ux_device_class_dfu_activate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted. + The device endpoints have to be dismounted and the dfu thread canceled. */ + status = _ux_device_class_dfu_deactivate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_REQUEST: + + /* The request command is used when the host sends a command on the control endpoint. */ + status = _ux_device_class_dfu_control_request(command); + + /* Return the completion status. */ + return(status); + + default: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_initialize.c b/common/usbx_device_classes/src/ux_device_class_dfu_initialize.c new file mode 100644 index 0000000..f65148f --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_dfu_initialize.c @@ -0,0 +1,213 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device DFU Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dfu.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dfu_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB DFU device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to dfu command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_descriptor_parse Parse a descriptor */ +/* _ux_utility_event_flags_create Create event flags */ +/* _ux_utility_event_flags_delete Delete event flags */ +/* _ux_utility_thread_create Create thread */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_dfu_initialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_DFU *dfu; +UX_SLAVE_CLASS_DFU_PARAMETER *dfu_parameter; +UX_SLAVE_CLASS *class; +UINT status; +UX_DFU_FUNCTIONAL_DESCRIPTOR dfu_functional_descriptor; +UCHAR *dfu_framework; +ULONG dfu_framework_length; +UCHAR descriptor_type; +ULONG descriptor_length; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Create an instance of the device dfu class. */ + dfu = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_DFU)); + + /* Check for successful allocation. */ + if (dfu == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save the address of the DFU instance inside the DFU container. */ + class -> ux_slave_class_instance = (VOID *) dfu; + + /* Get the pointer to the application parameters for the dfu class. */ + dfu_parameter = command -> ux_slave_class_command_parameter; + + /* Save the calling parameters in the class instance. */ + dfu -> ux_slave_class_dfu_instance_activate = dfu_parameter -> ux_slave_class_dfu_parameter_instance_activate; + dfu -> ux_slave_class_dfu_instance_deactivate = dfu_parameter -> ux_slave_class_dfu_parameter_instance_deactivate; + dfu -> ux_slave_class_dfu_read = dfu_parameter -> ux_slave_class_dfu_parameter_read; + dfu -> ux_slave_class_dfu_write = dfu_parameter -> ux_slave_class_dfu_parameter_write; + dfu -> ux_slave_class_dfu_get_status = dfu_parameter -> ux_slave_class_dfu_parameter_get_status; + dfu -> ux_slave_class_dfu_notify = dfu_parameter -> ux_slave_class_dfu_parameter_notify; + + /* Store the device dfu in the project structure. */ + _ux_system_slave -> ux_system_slave_dfu_framework = dfu_parameter -> ux_slave_class_dfu_parameter_framework; + _ux_system_slave -> ux_system_slave_dfu_framework_length = dfu_parameter -> ux_slave_class_dfu_parameter_framework_length; + + /* There is a DFU descriptor. It has a device descriptor, a configuration descriptor, + an interface descriptor and finally a functional descriptor. */ + dfu_framework = _ux_system_slave -> ux_system_slave_dfu_framework; + dfu_framework_length = _ux_system_slave -> ux_system_slave_dfu_framework_length; + + /* Parse the device framework and locate interfaces and endpoint descriptor(s). */ + while (dfu_framework_length != 0) + { + + /* Get the length of this descriptor. */ + descriptor_length = (ULONG) *dfu_framework; + + /* And its type. */ + descriptor_type = *(dfu_framework + 1); + + /* Is this the Functional descriptor ? */ + if (descriptor_type == UX_DFU_FUNCTIONAL_DESCRIPTOR_ITEM) + { + + /* Parse the DFU descriptor in something more readable. */ + _ux_utility_descriptor_parse(dfu_framework, + _ux_system_dfu_functional_descriptor_structure, + UX_DFU_FUNCTIONAL_DESCRIPTOR_ENTRIES, + (UCHAR *) &dfu_functional_descriptor); + + /* Retrieve the DFU capabilities and store them in the system. */ + _ux_system_slave -> ux_system_slave_device_dfu_capabilities = dfu_functional_descriptor.bmAttributes; + + /* Retrieve the DFU timeout value. */ + _ux_system_slave -> ux_system_slave_device_dfu_detach_timeout = dfu_functional_descriptor.wDetachTimeOut; + + /* Retrieve the DFU transfer size value. */ + _ux_system_slave -> ux_system_slave_device_dfu_transfer_size = dfu_functional_descriptor.wDetachTimeOut; + + /* In the system, state the DFU state machine. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_APP_IDLE; + + } + + /* Adjust what is left of the device framework. */ + dfu_framework_length -= descriptor_length; + + /* Point to the next descriptor. */ + dfu_framework += descriptor_length; + + } + + /* Create a event flag group for the dfu class to synchronize with the event interrupt thread. */ + status = _ux_utility_event_flags_create(&dfu -> ux_slave_class_dfu_event_flags_group, "ux_device_class_dfu_event_flag"); + + /* Check status. */ + if (status != UX_SUCCESS) + status = UX_EVENT_ERROR; + + /* Allocate some memory for the dfu thread stack. */ + if (status == UX_SUCCESS) + { + dfu -> ux_slave_class_dfu_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (dfu -> ux_slave_class_dfu_thread_stack == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* dfu needs a thread to watch for disconnect and timer event for the DFU_DETACH sequence. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_thread_create(&dfu -> ux_slave_class_dfu_thread , "ux_slave_class_dfu_thread", + _ux_device_class_dfu_thread, + (ULONG) (ALIGN_TYPE) class, (VOID *) dfu -> ux_slave_class_dfu_thread_stack, + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check the creation of this thread. */ + if (status != UX_SUCCESS) + status = UX_THREAD_ERROR; + } + + UX_THREAD_EXTENSION_PTR_SET(&(dfu -> ux_slave_class_dfu_thread), class) + + /* Return completion status. */ + if (status == UX_SUCCESS) + return(UX_SUCCESS); + + /* There is error, free resources. */ + /* The last resource, thread is not created or created error, no need to free. */ + + if (dfu -> ux_slave_class_dfu_thread_stack) + _ux_utility_memory_free(dfu -> ux_slave_class_dfu_thread_stack); + if (dfu -> ux_slave_class_dfu_event_flags_group.tx_event_flags_group_id != 0) + _ux_utility_event_flags_delete(&dfu -> ux_slave_class_dfu_event_flags_group); + + /* Detach from container and free instance memory. */ + class -> ux_slave_class_instance = UX_NULL; + _ux_utility_memory_free(dfu); + + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_dfu_thread.c b/common/usbx_device_classes/src/ux_device_class_dfu_thread.c new file mode 100644 index 0000000..c6fbbfc --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_dfu_thread.c @@ -0,0 +1,134 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device dfu Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_dfu.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_dfu_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the dfu class. It waits for the */ +/* dfu command to signal a DFU_DETACH stage and either force a */ +/* disconnect from the device or wait for the host to detach. */ +/* */ +/* INPUT */ +/* */ +/* dfu_class Address of dfu class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_event_flags_get Get event flags */ +/* _ux_utility_delay_ms Delay in milliseconds */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_dfu_thread(ULONG dfu_class) +{ + +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_DFU *dfu; +UX_SLAVE_DCD *dcd; +UINT status; +ULONG actual_flags; + + /* Cast properly the dfu instance. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_SLAVE_CLASS, dfu_class) + + /* Get the dfu instance from this class container. */ + dfu = (UX_SLAVE_CLASS_DFU *) class -> ux_slave_class_instance; + + /* This thread runs forever. */ + while(1) + { + + + /* Wait until we have a event sent by the application. */ + status = _ux_utility_event_flags_get(&dfu -> ux_slave_class_dfu_event_flags_group, (UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT | + UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET), + TX_OR_CLEAR, &actual_flags, TX_WAIT_FOREVER); + + /* Check the completion code and the actual flags returned. */ + if (status == UX_SUCCESS) + { + + /* Check the source of event. */ + if (actual_flags & UX_DEVICE_CLASS_DFU_THREAD_EVENT_DISCONNECT) + { + + /* We need to disconnect. The control command for DETACH is still being processed, wait 2-3 ms. */ + _ux_utility_delay_ms(2); + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Issue a Soft Disconnect. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_CHANGE_STATE, (VOID *) UX_DEVICE_FORCE_DISCONNECT); + + } + + /* Check the source of event. */ + if (actual_flags & UX_DEVICE_CLASS_DFU_THREAD_EVENT_WAIT_RESET) + { + + /* We need to wait for reset. Arm a timer. The timeout value is indicated in ms from + the device framework. */ + _ux_utility_delay_ms(_ux_system_slave -> ux_system_slave_device_dfu_detach_timeout); + + /* Check the mode. */ + if (_ux_system_slave -> ux_system_slave_device_dfu_mode == UX_DEVICE_CLASS_DFU_MODE_RUNTIME) + + /* We are still in RunTime mode. The host never reset. Revert to AppIdle state. */ + _ux_system_slave -> ux_system_slave_device_dfu_state_machine = UX_SYSTEM_DFU_STATE_APP_IDLE; + + } + } + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_hid_activate.c b/common/usbx_device_classes/src/ux_device_class_hid_activate.c new file mode 100644 index 0000000..fcb560a --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_activate.c @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function activates an instance of a HID device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to hid command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_thread_resume Resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_activate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_HID *hid; +UX_SLAVE_CLASS *class; +UX_SLAVE_ENDPOINT *endpoint_interrupt; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + hid = (UX_SLAVE_CLASS_HID *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Store the class instance into the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)hid; + + /* Now the opposite, store the interface in the class instance. */ + hid -> ux_slave_class_hid_interface = interface; + + /* Locate the endpoints. */ + endpoint_interrupt = interface -> ux_slave_interface_first_endpoint; + + /* Check if interrupt IN endpoint exists. */ + while (endpoint_interrupt != UX_NULL) + { + + if ((endpoint_interrupt -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN && + (endpoint_interrupt -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT) + { + + /* It's right endpoint we need. */ + break; + } + + /* Try next endpoint. */ + endpoint_interrupt = endpoint_interrupt -> ux_slave_endpoint_next_endpoint; + } + + /* Check if we found right endpoint. */ + if (endpoint_interrupt == UX_NULL) + return (UX_ERROR); + + /* Save the endpoint in the hid instance. */ + hid -> ux_device_class_hid_interrupt_endpoint = endpoint_interrupt; + + /* Resume thread. */ + _ux_utility_thread_resume(&class -> ux_slave_class_thread); + + /* If there is a activate function call it. */ + if (hid -> ux_slave_class_hid_instance_activate != UX_NULL) + { + + /* Invoke the application. */ + hid -> ux_slave_class_hid_instance_activate(hid); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_ACTIVATE, hid, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, hid, 0, 0, 0) + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_hid_control_request.c b/common/usbx_device_classes/src/ux_device_class_hid_control_request.c new file mode 100644 index 0000000..64d1b1f --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_control_request.c @@ -0,0 +1,190 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_control_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to hid class */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_class_hid_report_get Process Get_Report request */ +/* _ux_device_class_hid_report_set Process Set_Report request */ +/* _ux_device_class_hid_descriptor_send Send requested descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_control_request(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +UX_SLAVE_CLASS *class; +ULONG request; +ULONG request_value; +ULONG request_index; +ULONG request_length; +ULONG descriptor_type; +UCHAR duration; +UX_SLAVE_CLASS_HID *hid; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the pointer to the transfer request associated with the control endpoint. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Extract all necessary fields of the request. */ + request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST); + request_value = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE); + request_index = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_INDEX); + request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH); + + /* Duration - upper byte of wValue. */ + duration = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE + 1); + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the storage instance from this class container. */ + hid = (UX_SLAVE_CLASS_HID *) class -> ux_slave_class_instance; + + /* Here we proceed only the standard request we know of at the device level. */ + switch (request) + { + + case UX_DEVICE_CLASS_HID_COMMAND_GET_REPORT: + + /* Send the requested report to the host. */ + _ux_device_class_hid_report_get(hid, request_value, request_index, request_length); + break; + + case UX_DEVICE_CLASS_HID_COMMAND_SET_REPORT: + + /* Extract the descriptor type. */ + descriptor_type = (request_value & 0xff00) >> 8; + + /* Get the requested report from the host. */ + _ux_device_class_hid_report_set(hid, descriptor_type, request_index, request_length); + break; + + case UX_GET_DESCRIPTOR: + + /* Send the requested descriptor to the host. */ + _ux_device_class_hid_descriptor_send(hid, request_value, request_index, request_length); + break; + + case UX_DEVICE_CLASS_HID_COMMAND_GET_IDLE: + case UX_DEVICE_CLASS_HID_COMMAND_SET_IDLE: + + /* Ignore Report ID for now. */ + + if (request == UX_DEVICE_CLASS_HID_COMMAND_GET_IDLE) + { + + /* Send the idle rate. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR)hid -> ux_device_class_hid_event_idle_rate; + _ux_device_stack_transfer_request(transfer_request, 1, request_length); + } + else + { + + /* Accept the idle rate if it changes. */ + if ((UCHAR)hid -> ux_device_class_hid_event_idle_rate != duration) + { + + hid -> ux_device_class_hid_event_idle_rate = duration; + if (duration == 0) + { + + /* No need to repeat last report, no timeout. */ + hid -> ux_device_class_hid_event_wait_timeout = TX_WAIT_FOREVER; + } + else + { + + /* Calculate the timeout value. Weighted as 4ms. */ + hid -> ux_device_class_hid_event_wait_timeout = MS_TO_TICK((ULONG)duration << 2u); + + /* Be sure to have a timeout that is not zero. */ + if (hid -> ux_device_class_hid_event_wait_timeout == 0) + hid -> ux_device_class_hid_event_wait_timeout ++; + + /* Set an event to wake up the interrupt thread. */ + _ux_utility_event_flags_set(&hid -> ux_device_class_hid_event_flags_group, UX_DEVICE_CLASS_HID_NEW_IDLE_RATE, TX_OR); + } + } + } + break; + + case UX_DEVICE_CLASS_HID_COMMAND_GET_PROTOCOL: + case UX_DEVICE_CLASS_HID_COMMAND_SET_PROTOCOL: + + /* Not supported now. */ + + default: + + /* Unknown function. It's not handled. */ + return(UX_ERROR); + } + + /* It's handled. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_hid_deactivate.c b/common/usbx_device_classes/src/ux_device_class_hid_deactivate.c new file mode 100644 index 0000000..4f4892d --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_deactivate.c @@ -0,0 +1,99 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivate an instance of the hid class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_all_request_abort Abort all transfers */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_deactivate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_HID *hid; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + hid = (UX_SLAVE_CLASS_HID *) class -> ux_slave_class_instance; + + /* Terminate the transactions pending on the endpoints. */ + _ux_device_stack_transfer_all_request_abort(hid -> ux_device_class_hid_interrupt_endpoint, UX_TRANSFER_BUS_RESET); + + /* If there is a deactivate function call it. */ + if (hid -> ux_slave_class_hid_instance_deactivate != UX_NULL) + { + /* Invoke the application. */ + hid -> ux_slave_class_hid_instance_deactivate(hid); + } + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_DEACTIVATE, hid, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(hid); + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_hid_descriptor_send.c b/common/usbx_device_classes/src/ux_device_class_hid_descriptor_send.c new file mode 100644 index 0000000..61b41f9 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_descriptor_send.c @@ -0,0 +1,212 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_descriptor_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends back the class descriptor required by the host. */ +/* */ +/* INPUT */ +/* */ +/* descriptor_type Descriptor type */ +/* descriptor_index Index of descriptor */ +/* host_length Length requested by host */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_dcd_function) DCD dispatch function */ +/* _ux_device_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_copy Memory copy */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_descriptor_send(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, + ULONG request_index, ULONG host_length) +{ + +UX_SLAVE_DCD *dcd; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_ENDPOINT *endpoint; +UCHAR * device_framework; +UCHAR * device_framework_end; +ULONG descriptor_length; +UINT status = UX_ERROR; +ULONG length; + + UX_PARAMETER_NOT_USED(request_index); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_DESCRIPTOR_SEND, hid, descriptor_type, request_index, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the DCD. */ + dcd = &_ux_system_slave -> ux_system_slave_dcd; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the control endpoint associated with the device. */ + endpoint = &device -> ux_slave_device_control_endpoint; + + /* Get the pointer to the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Set the direction to OUT. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* Shift the descriptor type in the low byte field. */ + descriptor_type = (UCHAR) ((descriptor_type >> 8) & 0xff); + + /* What type of descriptor do we need to return? */ + switch (descriptor_type) + { + + case UX_DEVICE_CLASS_HID_DESCRIPTOR_HID: + + /* We should have a HID descriptor as part of the config descriptor. */ + device_framework = _ux_system_slave -> ux_system_slave_device_framework; + device_framework_end = device_framework + _ux_system_slave -> ux_system_slave_device_framework_length; + + /* Parse the device framework and locate the HID descriptor. + There is only one HID descriptor. */ + while (device_framework < device_framework_end) + { + + /* Get the type of the current descriptor. */ + descriptor_type = *(device_framework + 1); + + /* And its length. */ + descriptor_length = (ULONG) *device_framework; + + /* Check if this is a HID report descriptor. */ + if (descriptor_type == UX_DEVICE_CLASS_HID_DESCRIPTOR_HID) + { + /* Ensure the host does not demand a length beyond our descriptor (Windows does that) + and do not return more than what is allowed. */ + if (descriptor_length < host_length) + length = descriptor_length; + else + length = host_length; + + /* Copy the device descriptor into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + device_framework, length); + + /* We can return the configuration descriptor. */ + status = _ux_device_stack_transfer_request(transfer_request, length, host_length); + break; + + } + + /* Point to the next descriptor. */ + device_framework += descriptor_length; + } + + /* Stall the endpoint if not found or corrupt. */ + if (device_framework >= device_framework_end) + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + + break; + + case UX_DEVICE_CLASS_HID_DESCRIPTOR_REPORT: + + /* Get the length of entire configuration descriptor. */ + descriptor_length = hid -> ux_device_class_hid_report_length; + + /* Ensure the host does not demand a length beyond our descriptor (Windows does that) + and do not return more than what is allowed. */ + if (descriptor_length < host_length) + length = descriptor_length; + else + length = host_length; + + /* Check buffer length, since total descriptors length may exceed buffer... */ + if (length > UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Stall the endpoint. */ + status = dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + break; + } + + /* Copy the device descriptor into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + hid -> ux_device_class_hid_report_address, length); + + /* We can return the report descriptor. */ + status = _ux_device_stack_transfer_request(transfer_request, length, host_length); + break; + + case UX_DEVICE_CLASS_HID_DESCRIPTOR_PHYSICAL: + + /* Not treated for now. Fall through and Stall endpoint. */ + + default: + + /* Stall the endpoint. */ + dcd -> ux_slave_dcd_function(dcd, UX_DCD_STALL_ENDPOINT, endpoint); + return(UX_ERROR); + } + + /* Return the status to the caller. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_hid_entry.c b/common/usbx_device_classes/src/ux_device_class_hid_entry.c new file mode 100644 index 0000000..9a99766 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_entry.c @@ -0,0 +1,147 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_class_device_hid_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the hid class. It */ +/* will be called by the device stack enumeration module when the */ +/* host has sent a SET_CONFIGURATION command and the hid interface */ +/* needs to be mounted. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_hid_initialize Initialize hid class */ +/* _ux_device_class_hid_uninitialize Uninitialize hid class */ +/* _ux_device_class_hid_activate Activate hid class */ +/* _ux_device_class_hid_deactivate Deactivate hid class */ +/* _ux_device_class_hid_control_request Request control */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_entry(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_slave_class_command_request) + { + + case UX_SLAVE_CLASS_COMMAND_INITIALIZE: + + /* Call the init function of the HID class. */ + status = _ux_device_class_hid_initialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_UNINITIALIZE: + + /* Call the init function of the HID class. */ + status = _ux_device_class_hid_uninitialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_QUERY: + + /* Check the CLASS definition in the interface descriptor. */ + if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_HID_CLASS) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_SLAVE_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the host has sent a SET_CONFIGURATION command + and this interface has to be mounted. Both Bulk endpoints have to be mounted + and the hid thread needs to be activated. */ + status = _ux_device_class_hid_activate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted. + The device endpoints have to be dismounted and the hid thread canceled. */ + status = _ux_device_class_hid_deactivate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_REQUEST: + + /* The request command is used when the host sends a command on the control endpoint. */ + status = _ux_device_class_hid_control_request(command); + + /* Return the completion status. */ + return(status); + + default: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_hid_event_get.c b/common/usbx_device_classes/src/ux_device_class_hid_event_get.c new file mode 100644 index 0000000..ab1ce83 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_event_get.c @@ -0,0 +1,115 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_event_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks if there is an event from the application */ +/* */ +/* INPUT */ +/* */ +/* hid Address of hid class */ +/* event Pointer of the event */ +/* */ +/* OUTPUT */ +/* */ +/* status UX_SUCCESS if there is an */ +/* event */ +/* CALLS */ +/* */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_event_get(UX_SLAVE_CLASS_HID *hid, + UX_SLAVE_CLASS_HID_EVENT *hid_event) +{ + +UX_SLAVE_CLASS_HID_EVENT *current_hid_event; +UX_SLAVE_DEVICE *device; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_EVENT_GET, hid, hid_event, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Check the device state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + return(UX_DEVICE_HANDLE_UNKNOWN); + + /* Check if the head and the tail of the event array is the same. */ + if (hid -> ux_device_class_hid_event_array_head == + hid -> ux_device_class_hid_event_array_tail) + + /* No event to report. */ + return(UX_ERROR); + + /* There is an event to report, get the current pointer to the event. */ + current_hid_event = hid -> ux_device_class_hid_event_array_tail; + + /* fill in the event structure from the user. */ + hid_event -> ux_device_class_hid_event_length = current_hid_event -> ux_device_class_hid_event_length; + _ux_utility_memory_copy(hid_event -> ux_device_class_hid_event_buffer, current_hid_event -> ux_device_class_hid_event_buffer, + current_hid_event -> ux_device_class_hid_event_length); + + /* Adjust the tail pointer. Check if we are at the end. */ + if ((current_hid_event + 1) == hid -> ux_device_class_hid_event_array_end) + + /* We are at the end, go back to the beginning. */ + hid -> ux_device_class_hid_event_array_tail = hid -> ux_device_class_hid_event_array; + + else + /* We are not at the end, increment the tail position. */ + hid -> ux_device_class_hid_event_array_tail++; + + /* Return event status to the user. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_hid_event_set.c b/common/usbx_device_classes/src/ux_device_class_hid_event_set.c new file mode 100644 index 0000000..ce83453 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_event_set.c @@ -0,0 +1,157 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_event_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends an event to the hid class. It is processed */ +/* asynchronously by the interrupt thread. */ +/* */ +/* INPUT */ +/* */ +/* hid Address of hid class */ +/* event Pointer of the event */ +/* */ +/* OUTPUT */ +/* */ +/* status UX_SUCCESS if there is an */ +/* event */ +/* CALLS */ +/* */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_event_flags_set Set event flags */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_event_set(UX_SLAVE_CLASS_HID *hid, + UX_SLAVE_CLASS_HID_EVENT *hid_event) +{ + +UX_SLAVE_CLASS_HID_EVENT *current_hid_event; +UX_SLAVE_CLASS_HID_EVENT *next_hid_event; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_EVENT_SET, hid, hid_event, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Current position of the head. */ + current_hid_event = hid -> ux_device_class_hid_event_array_head; + + /* If the pointer is NULL, the round robin buffer has not been activated. */ + if (current_hid_event == UX_NULL) + return (UX_ERROR); + + /* Calculate the next position. */ + if ((current_hid_event + 1) == hid -> ux_device_class_hid_event_array_end) + + /* We are at the end, go back to the beginning. */ + next_hid_event = hid -> ux_device_class_hid_event_array; + + else + + /* We are not at the end, increment the head position. */ + next_hid_event = current_hid_event + 1; + + + /* Any place left for this event ? */ + if (next_hid_event == hid -> ux_device_class_hid_event_array_tail) + return (UX_ERROR); + + /* There is an event to report, get the current pointer to the event. */ + current_hid_event = hid -> ux_device_class_hid_event_array_head; + + /* Update the head. */ + hid -> ux_device_class_hid_event_array_head = next_hid_event; + + /* Check if this event has a report ID. */ + if (hid -> ux_device_class_hid_report_id == UX_TRUE) + { + + /* Yes, there's a report ID. Check to see if our event buffer can also + fit the extra byte. */ + if (hid_event -> ux_device_class_hid_event_length + 1 > UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return overflow error. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Store the report ID. */ + *current_hid_event -> ux_device_class_hid_event_buffer = (UCHAR)(hid_event -> ux_device_class_hid_event_report_id); + + /* Store the data itself. */ + _ux_utility_memory_copy(current_hid_event -> ux_device_class_hid_event_buffer + 1, hid_event -> ux_device_class_hid_event_buffer, + hid_event -> ux_device_class_hid_event_length); + + /* fill in the event structure from the user. */ + current_hid_event -> ux_device_class_hid_event_length = hid_event -> ux_device_class_hid_event_length + 1; + } + else + { + + /* No report ID to consider. */ + _ux_utility_memory_copy(current_hid_event -> ux_device_class_hid_event_buffer, hid_event -> ux_device_class_hid_event_buffer, + hid_event -> ux_device_class_hid_event_length); + + /* fill in the event structure from the user. */ + current_hid_event -> ux_device_class_hid_event_length = hid_event -> ux_device_class_hid_event_length; + } + + /* Set an event to wake up the interrupt thread. */ + _ux_utility_event_flags_set(&hid -> ux_device_class_hid_event_flags_group, UX_DEVICE_CLASS_HID_NEW_EVENT, TX_OR); + + /* Return event status to the user. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_hid_initialize.c b/common/usbx_device_classes/src/ux_device_class_hid_initialize.c new file mode 100644 index 0000000..9141a98 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_initialize.c @@ -0,0 +1,184 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB HID device. */ +/* This function is called by the class register function. It is only */ +/* done once. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to hid command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_thread_create Create thread */ +/* _ux_utility_thread_delete Delete thread */ +/* _ux_utility_event_flags_create Create event flags group */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_initialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_HID *hid; +UX_SLAVE_CLASS_HID_PARAMETER *hid_parameter; +UX_SLAVE_CLASS *class; +UINT status = UX_SUCCESS; + + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Create an instance of the device hid class. */ + hid = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_HID)); + + /* Check for successful allocation. */ + if (hid == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save the address of the HID instance inside the HID container. */ + class -> ux_slave_class_instance = (VOID *) hid; + + /* Allocate some memory for the thread stack. */ + class -> ux_slave_class_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (class -> ux_slave_class_thread_stack == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + + /* This instance needs to be running in a different thread. So start + a new thread. We pass a pointer to the class to the new thread. This thread + does not start until we have a instance of the class. */ + if (status == UX_SUCCESS) + status = _ux_utility_thread_create(&class -> ux_slave_class_thread, "ux_slave_hid_thread", + _ux_device_class_hid_interrupt_thread, + (ULONG) (ALIGN_TYPE) class, (VOID *) class -> ux_slave_class_thread_stack, + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_DONT_START); + + /* Check the creation of this thread. */ + if (status == UX_SUCCESS) + { + + UX_THREAD_EXTENSION_PTR_SET(&(class -> ux_slave_class_thread), class) + + /* Get the pointer to the application parameters for the hid class. */ + hid_parameter = command -> ux_slave_class_command_parameter; + + /* Store all the application parameter information about the report. */ + hid -> ux_device_class_hid_report_address = hid_parameter -> ux_device_class_hid_parameter_report_address; + hid -> ux_device_class_hid_report_length = hid_parameter -> ux_device_class_hid_parameter_report_length; + hid -> ux_device_class_hid_report_id = hid_parameter -> ux_device_class_hid_parameter_report_id; + + /* Store the callback function. */ + hid -> ux_device_class_hid_callback = hid_parameter -> ux_device_class_hid_parameter_callback; + hid -> ux_device_class_hid_get_callback = hid_parameter -> ux_device_class_hid_parameter_get_callback; + + /* Create the event array. */ + hid -> ux_device_class_hid_event_array = _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_HID_EVENT), UX_DEVICE_CLASS_HID_MAX_EVENTS_QUEUE); + + /* Check for successful allocation. */ + if (hid -> ux_device_class_hid_event_array != UX_NULL) + { + + /* Initialize the head and tail of the notification round robin buffers. + At first, the head and tail are pointing to the beginning of the array. */ + hid -> ux_device_class_hid_event_array_head = hid -> ux_device_class_hid_event_array; + hid -> ux_device_class_hid_event_array_tail = hid -> ux_device_class_hid_event_array; + hid -> ux_device_class_hid_event_array_end = hid -> ux_device_class_hid_event_array + UX_DEVICE_CLASS_HID_MAX_EVENTS_QUEUE; + + /* Store the start and stop signals if needed by the application. */ + hid -> ux_slave_class_hid_instance_activate = hid_parameter -> ux_slave_class_hid_instance_activate; + hid -> ux_slave_class_hid_instance_deactivate = hid_parameter -> ux_slave_class_hid_instance_deactivate; + + /* By default no event wait timeout. */ + hid -> ux_device_class_hid_event_wait_timeout = TX_WAIT_FOREVER; + + /* Create a event flag group for the hid class to synchronize with the event interrupt thread. */ + status = _ux_utility_event_flags_create(&hid -> ux_device_class_hid_event_flags_group, "ux_device_class_hid_event_flag"); + + /* Check status. */ + if (status == UX_SUCCESS) + return(status); + + /* It's event error. */ + status = UX_EVENT_ERROR; + } + else + status = UX_MEMORY_INSUFFICIENT; + + /* Delete thread. */ + _ux_utility_thread_delete(&class -> ux_slave_class_thread); + } + else + status = (UX_THREAD_ERROR); + + /* Free stack. */ + if (class -> ux_slave_class_thread_stack) + _ux_utility_memory_free(class -> ux_slave_class_thread_stack); + + /* Unmount instance. */ + class -> ux_slave_class_instance = UX_NULL; + + /* Free HID instance. */ + _ux_utility_memory_free(hid); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_hid_interrupt_thread.c b/common/usbx_device_classes/src/ux_device_class_hid_interrupt_thread.c new file mode 100644 index 0000000..4274a06 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_interrupt_thread.c @@ -0,0 +1,178 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_interrupt_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the hid interrupt endpoint */ +/* */ +/* INPUT */ +/* */ +/* hid_class Address of hid class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_event_flags_get Get event flags */ +/* _ux_device_class_hid_event_get Get HID event */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_thread_suspend Suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_hid_interrupt_thread(ULONG hid_class) +{ + +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_HID *hid; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request_in; +UX_SLAVE_CLASS_HID_EVENT hid_event; +UINT status; +UCHAR *buffer; +ULONG actual_flags; + + + /* Cast properly the hid instance. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_SLAVE_CLASS, hid_class) + + /* Get the hid instance from this class container. */ + hid = (UX_SLAVE_CLASS_HID *) class -> ux_slave_class_instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + + /* All HID events are on the interrupt endpoint IN, from the host. */ + transfer_request_in = &hid -> ux_device_class_hid_interrupt_endpoint -> ux_slave_endpoint_transfer_request; + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Wait until we have a event sent by the application + or a change in the idle state to send last or empty report. */ + status = _ux_utility_event_flags_get(&hid -> ux_device_class_hid_event_flags_group, + UX_DEVICE_CLASS_HID_EVENTS_MASK, TX_OR_CLEAR, &actual_flags, + hid -> ux_device_class_hid_event_wait_timeout); + + /* If there is no event, check if we have timeout defined. */ + if (status == TX_NO_EVENTS) + { + + /* There is no event exists on timeout, insert last. */ + + /* If last request is sent, repeat it, else fill zeros. */ + if (transfer_request_in -> ux_slave_transfer_request_requested_length) + { + hid_event.ux_device_class_hid_event_length = transfer_request_in -> ux_slave_transfer_request_requested_length; + _ux_utility_memory_copy(hid_event.ux_device_class_hid_event_buffer, + transfer_request_in -> ux_slave_transfer_request_data_pointer, + hid_event.ux_device_class_hid_event_length); + } + else + { + hid_event.ux_device_class_hid_event_report_id = 0; + hid_event.ux_device_class_hid_event_length = transfer_request_in -> ux_slave_transfer_request_endpoint -> ux_slave_endpoint_descriptor.wMaxPacketSize & 0x7FF; + _ux_utility_memory_set(hid_event.ux_device_class_hid_event_buffer, 0, + hid_event.ux_device_class_hid_event_length); + } + _ux_device_class_hid_event_set(hid, &hid_event); + + /* Continue to process queue. */ + status = UX_SUCCESS; + } + + /* Check the completion code. */ + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + + /* Do not proceed. */ + return; + } + + + /* Check if we have an event to report. */ + while (_ux_device_class_hid_event_get(hid, &hid_event) == UX_SUCCESS) + { + + /* Prepare the event data payload from the hid event structure. Get a pointer to the buffer area. */ + buffer = transfer_request_in -> ux_slave_transfer_request_data_pointer; + + /* Copy the event buffer into the target buffer. */ + _ux_utility_memory_copy(buffer, hid_event.ux_device_class_hid_event_buffer, hid_event.ux_device_class_hid_event_length); + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request_in, hid_event.ux_device_class_hid_event_length, + hid_event.ux_device_class_hid_event_length); + + /* Check error code. We don't want to invoke the error callback + if the device was disconnected, since that's expected. */ + if (status != UX_SUCCESS && status != UX_TRANSFER_BUS_RESET) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + } + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ + _ux_utility_thread_suspend(&class -> ux_slave_class_thread); + } +} diff --git a/common/usbx_device_classes/src/ux_device_class_hid_report_get.c b/common/usbx_device_classes/src/ux_device_class_hid_report_get.c new file mode 100644 index 0000000..4782148 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_report_get.c @@ -0,0 +1,172 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_report_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns a report to the host. */ +/* */ +/* INPUT */ +/* */ +/* descriptor_type Descriptor type */ +/* descriptor_index Index of descriptor */ +/* host_length Length requested by host */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_hid_event_get Get HID event */ +/* _ux_device_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_set Set memory */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_report_get(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, + ULONG request_index, ULONG host_length) +{ + +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_ENDPOINT *endpoint; +UCHAR report_id; +UCHAR report_type; +UX_SLAVE_CLASS_HID_EVENT hid_event; +ULONG hid_event_length; +UCHAR *buffer; +UINT status = UX_ERROR; + + UX_PARAMETER_NOT_USED(descriptor_type); + UX_PARAMETER_NOT_USED(request_index); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_REPORT_GET, hid, descriptor_type, request_index, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the control endpoint associated with the device. */ + endpoint = &device -> ux_slave_device_control_endpoint; + + /* Get the pointer to the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Get report ID (wValue.lower) and report type (wValue.higher). */ + report_id = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE + 0); + report_type = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_VALUE + 1); + + /* Set the direction to OUT. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* Prepare the event data payload from the hid event structure. Get a pointer to the buffer area. */ + buffer = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Initialize event fields. */ + hid_event.ux_device_class_hid_event_report_id = report_id; + hid_event.ux_device_class_hid_event_report_type = report_type; + hid_event.ux_device_class_hid_event_length = UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH; + + /* If it's input report without ID try to get it from event queue head. */ + if (report_type == UX_DEVICE_CLASS_HID_REPORT_TYPE_INPUT && + hid -> ux_device_class_hid_report_id != UX_TRUE) + + /* Check if we have an event to report. */ + status = _ux_device_class_hid_event_get(hid, &hid_event); + + /* Try to get event from application callback. */ + else + { + + /* Let application fill event. */ + if (hid -> ux_device_class_hid_get_callback != UX_NULL) + status = hid -> ux_device_class_hid_get_callback(hid, &hid_event); + } + + if (status == UX_SUCCESS) + { + + /* Get the length to send back to the host. */ + if (host_length < hid_event.ux_device_class_hid_event_length) + hid_event_length = host_length; + else + hid_event_length = hid_event.ux_device_class_hid_event_length; + + /* First reset it. */ + _ux_utility_memory_set(buffer, 0, hid_event_length); + + /* Copy the event buffer into the target buffer. */ + _ux_utility_memory_copy(buffer, hid_event.ux_device_class_hid_event_buffer, hid_event_length); + } + else + { + + /* There's no event, so send back zero'd memory. */ + + /* Get the length to send back to the host. */ + if (host_length < UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH) + hid_event_length = host_length; + else + hid_event_length = UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH; + + /* Reset it. */ + _ux_utility_memory_set(buffer, 0, hid_event_length); + } + + /* We can send the report. */ + status = _ux_device_stack_transfer_request(transfer_request, hid_event_length, host_length); + + /* Return the status to the caller. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_hid_report_set.c b/common/usbx_device_classes/src/ux_device_class_hid_report_set.c new file mode 100644 index 0000000..69ec450 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_report_set.c @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_report_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets from the control pipe a report to be set from */ +/* the host. */ +/* */ +/* INPUT */ +/* */ +/* descriptor_type Descriptor type */ +/* descriptor_index Index of descriptor */ +/* host_length Length requested by host */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_copy Memory copy */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Device Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_report_set(UX_SLAVE_CLASS_HID *hid, ULONG descriptor_type, + ULONG request_index, ULONG host_length) +{ + +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_ENDPOINT *endpoint; +UX_SLAVE_CLASS_HID_EVENT hid_event; +UCHAR *hid_buffer; + + UX_PARAMETER_NOT_USED(request_index); + UX_PARAMETER_NOT_USED(host_length); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_HID_REPORT_SET, hid, descriptor_type, request_index, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the control endpoint associated with the device. */ + endpoint = &device -> ux_slave_device_control_endpoint; + + /* Get the pointer to the transfer request associated with the endpoint. */ + transfer_request = &endpoint -> ux_slave_endpoint_transfer_request; + + /* Set the event type to OUTPUT. */ + hid_event.ux_device_class_hid_event_report_type = descriptor_type; + + /* Get HID data address. */ + hid_buffer = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Check for report ID in this HID descriptor. */ + if (hid -> ux_device_class_hid_report_id == UX_TRUE) + { + /* Set the report ID, First byte of data payload. */ + hid_event.ux_device_class_hid_event_report_id = (ULONG) *hid_buffer; + + /* Set the length = total length - report ID. */ + hid_event.ux_device_class_hid_event_length = transfer_request -> ux_slave_transfer_request_actual_length -1; + + /* Set HID data after report ID. */ + hid_buffer++; + } + + else + { + /* Set the report ID, not used here. */ + hid_event.ux_device_class_hid_event_report_id = 0; + + /* Set the length. */ + hid_event.ux_device_class_hid_event_length = transfer_request -> ux_slave_transfer_request_actual_length; + } + + /* Copy the buffer received from the host. Check for overflow. */ + if (hid_event.ux_device_class_hid_event_length > UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH) + + /* Overflow detected. */ + hid_event.ux_device_class_hid_event_length = UX_DEVICE_CLASS_HID_EVENT_BUFFER_LENGTH; + + /* Now we can safely copy the payload. */ + _ux_utility_memory_copy(hid_event.ux_device_class_hid_event_buffer, hid_buffer, + hid_event.ux_device_class_hid_event_length); + + /* If there is a callback defined by the application, send the hid event to it. */ + if (hid -> ux_device_class_hid_callback != UX_NULL) + + /* Callback exists. */ + hid -> ux_device_class_hid_callback(hid, &hid_event); + + /* Return the status to the caller. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_hid_uninitialize.c b/common/usbx_device_classes/src/ux_device_class_hid_uninitialize.c new file mode 100644 index 0000000..3477161 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_hid_uninitialize.c @@ -0,0 +1,102 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_hid.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_hid_uninitialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function uninitializes the USB HID device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to hid command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_thread_delete Remove storage thread. */ +/* _ux_utility_memory_free Free memory used by storage */ +/* _ux_utility_event_flags_delete Remove flag event structure */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_hid_uninitialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_HID *hid; +UX_SLAVE_CLASS *class; + + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + hid = (UX_SLAVE_CLASS_HID *) class -> ux_slave_class_instance; + + /* Remove HID thread. */ + _ux_utility_thread_delete(&class -> ux_slave_class_thread); + + /* Remove the thread used by HID. */ + _ux_utility_memory_free(class -> ux_slave_class_thread_stack); + + /* Delete the event flag group for the hid class. */ + _ux_utility_event_flags_delete(&hid -> ux_device_class_hid_event_flags_group); + + /* Free memory for the array. */ + _ux_utility_memory_free(hid -> ux_device_class_hid_event_array); + + /* Free the resources. */ + _ux_utility_memory_free(hid); + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_activate.c b/common/usbx_device_classes/src/ux_device_class_pima_activate.c new file mode 100644 index 0000000..06a1a02 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_activate.c @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function activates the USB Pima device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to pima command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_thread_resume Resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_activate(UX_SLAVE_CLASS_COMMAND *command) +{ + + UINT status; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_PIMA *pima; +UX_SLAVE_CLASS *class; +UX_SLAVE_ENDPOINT *endpoint_in; +UX_SLAVE_ENDPOINT *endpoint_out; +UX_SLAVE_ENDPOINT *endpoint_interrupt; + + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Store the class instance in the container. */ + pima = (UX_SLAVE_CLASS_PIMA *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Store the class instance into the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)pima; + + /* Now the opposite, store the interface in the class instance. */ + pima -> ux_slave_class_pima_interface = interface; + + /* Locate the endpoints. */ + endpoint_in = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint_in -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) + { + + /* Wrong direction, we found the OUT endpoint first. */ + endpoint_out = endpoint_in; + + /* So the next endpoint has to be the IN endpoint. */ + endpoint_in = endpoint_out -> ux_slave_endpoint_next_endpoint; + + /* And the endpoint after that interrupt. */ + endpoint_interrupt = endpoint_in -> ux_slave_endpoint_next_endpoint; + + } + else + { + + /* We found the endpoint IN first, so next endpoint is OUT. */ + endpoint_out = endpoint_in -> ux_slave_endpoint_next_endpoint; + + /* And the endpoint after that interrupt. */ + endpoint_interrupt = endpoint_out -> ux_slave_endpoint_next_endpoint; + } + + /* Save the endpoints in the pima instance. */ + pima -> ux_device_class_pima_bulk_in_endpoint = endpoint_in; + pima -> ux_device_class_pima_bulk_out_endpoint = endpoint_out; + pima -> ux_device_class_pima_interrupt_endpoint = endpoint_interrupt; + + /* Resume thread. */ + status = _ux_utility_thread_resume(&class -> ux_slave_class_thread); + + /* If there is a activate function call it. */ + if (pima -> ux_device_class_pima_instance_activate != UX_NULL) + { + /* Invoke the application. */ + pima -> ux_device_class_pima_instance_activate(pima); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_ACTIVATE, pima, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, pima, 0, 0, 0) + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_control_request.c b/common/usbx_device_classes/src/ux_device_class_pima_control_request.c new file mode 100644 index 0000000..65a3172 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_control_request.c @@ -0,0 +1,159 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_control_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_transfer_abort Transfer abort */ +/* _ux_device_class_pima_event_set Put PIMA event into queue */ +/* _ux_utility_short_put Put 16-bit value into buffer */ +/* */ +/* CALLED BY */ +/* */ +/* PIMA Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_control_request(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_PIMA_EVENT pima_event; +ULONG request; +UX_SLAVE_CLASS_PIMA *pima; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the pointer to the transfer request associated with the control endpoint. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Extract all necessary fields of the request. */ + request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST); + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the storage instance from this class container. */ + pima = (UX_SLAVE_CLASS_PIMA *) class -> ux_slave_class_instance; + + /* Here we proceed only the standard request we know of at the device level. */ + switch (request) + { + + case UX_DEVICE_CLASS_PIMA_REQUEST_CANCEL_COMMAND: + + /* We need to cancel the request that is currently pending. It could be either + on the bulk in or bulk out endpoint. Load the bulk in transfer request first. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* And check if we have something waiting on this one. */ + if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) + + /* Yes, abort it. */ + _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); + + /* Maybe the bulk out is busy too. */ + transfer_request = &pima -> ux_device_class_pima_bulk_out_endpoint -> ux_slave_endpoint_transfer_request; + + /* And check if we have something waiting on this one. */ + if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_PENDING) + + /* Yes, abort it. */ + _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_STATUS_ABORT); + + /* The host is now waiting for an event of transfer cancelled to proceed. + Prepare an event command and set the event code to transaction cancelled*/ + pima_event.ux_device_class_pima_event_code = UX_DEVICE_CLASS_PIMA_EC_CANCEL_TRANSACTION; + + /* Set all parameters to a 0 value. */ + pima_event.ux_device_class_pima_event_parameter_1 = 0; + pima_event.ux_device_class_pima_event_parameter_2 = 0; + pima_event.ux_device_class_pima_event_parameter_3 = 0; + + /* Send the pima event into the queue. This will be processed by an asynchronous thread. */ + _ux_device_class_pima_event_set(pima, &pima_event); + + break ; + + case UX_DEVICE_CLASS_PIMA_REQUEST_STATUS_COMMAND: + + /* Fill the status data payload. First with length. */ + _ux_utility_short_put(transfer_request -> ux_slave_transfer_request_data_pointer, 4); + + /* Then the status. */ + _ux_utility_short_put(transfer_request -> ux_slave_transfer_request_data_pointer + 2, UX_DEVICE_CLASS_PIMA_RC_OK); + + /* We have a request to obtain the status of the MTP. */ + _ux_device_stack_transfer_request(transfer_request, 4, 4); + + break ; + + default: + + /* Unknown function. It's not handled. */ + return(UX_ERROR); + } + + /* It's handled. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_data.c b/common/usbx_device_classes/src/ux_device_class_pima_data.c new file mode 100644 index 0000000..79eeb77 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_data.c @@ -0,0 +1,274 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_class_device_pima_data PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This module contains all the data definition used by the PIMA */ +/* device class. */ +/* */ +/* INPUT */ +/* */ +/* OUTPUT */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +/* Define PIMA vendor extension descriptor. This is a regular string that needs to be put into unicode. */ +UCHAR _ux_device_class_pima_vendor_extension_descriptor[] = { +#ifdef UX_PIMA_WITH_MTP_SUPPORT + "microsoft.com: 1.0; microsoft.com/WMPPD: 11.0; microsoft.com/WMPPD: 10.0; microsoft.com/WMDRMPD: 10.1;" +#else + 0 +#endif + }; + +/* Define PIMA supported operations. The last entry MUST be a zero. The DeviceInfoSet command + will parse this array and compute the number of functions supported and return it to the + host. */ + +USHORT _ux_device_class_pima_supported_operations[] = { + + UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_INFO, + UX_DEVICE_CLASS_PIMA_OC_OPEN_SESSION, + UX_DEVICE_CLASS_PIMA_OC_CLOSE_SESSION, + UX_DEVICE_CLASS_PIMA_OC_GET_STORAGE_IDS, + UX_DEVICE_CLASS_PIMA_OC_GET_STORAGE_INFO, + UX_DEVICE_CLASS_PIMA_OC_GET_NUM_OBJECTS, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_HANDLES, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_INFO, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT, + UX_DEVICE_CLASS_PIMA_OC_GET_THUMB, + UX_DEVICE_CLASS_PIMA_OC_GET_PARTIAL_OBJECT, + UX_DEVICE_CLASS_PIMA_OC_DELETE_OBJECT, + UX_DEVICE_CLASS_PIMA_OC_SEND_OBJECT_INFO, + UX_DEVICE_CLASS_PIMA_OC_SEND_OBJECT, + UX_DEVICE_CLASS_PIMA_OC_INITIATE_CAPTURE, + UX_DEVICE_CLASS_PIMA_OC_FORMAT_STORE, + UX_DEVICE_CLASS_PIMA_OC_RESET_DEVICE, +#ifdef UX_PIMA_WITH_MTP_SUPPORT + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROPS_SUPPORTED, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROP_DESC, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROP_VALUE, + UX_DEVICE_CLASS_PIMA_OC_SET_OBJECT_PROP_VALUE, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_REFERENCES, + UX_DEVICE_CLASS_PIMA_OC_SET_OBJECT_REFERENCES, +#endif + 0 + }; + + +/* Define PIMA supported events. The last entry MUST be a zero. The DeviceInfoSet command + will parse this array and compute the number of functions supported and return it to the + host. */ + +USHORT _ux_device_class_pima_supported_events[] = { + + UX_DEVICE_CLASS_PIMA_EC_CANCEL_TRANSACTION, + UX_DEVICE_CLASS_PIMA_EC_OBJECT_ADDED, + UX_DEVICE_CLASS_PIMA_EC_OBJECT_REMOVED, + UX_DEVICE_CLASS_PIMA_EC_STORE_ADDED, + UX_DEVICE_CLASS_PIMA_EC_STORE_REMOVED, + UX_DEVICE_CLASS_PIMA_EC_DEVICE_PROP_CHANGED, + UX_DEVICE_CLASS_PIMA_EC_OBJECT_INFO_CHANGED, + UX_DEVICE_CLASS_PIMA_EC_DEVICE_INFO_CHANGED, + UX_DEVICE_CLASS_PIMA_EC_REQUEST_OBJECT_TRANSFER, + UX_DEVICE_CLASS_PIMA_EC_STORE_FULL, + UX_DEVICE_CLASS_PIMA_EC_DEVICE_RESET, + UX_DEVICE_CLASS_PIMA_EC_STORAGE_INFO_CHANGED, + UX_DEVICE_CLASS_PIMA_EC_CAPTURE_COMPLETE, + UX_DEVICE_CLASS_PIMA_EC_UNREPORTED_STATUS, + 0 + }; + +/* Define PIMA supported device properties. The last entry MUST be a zero. The DeviceInfoSet command + will parse this array and compute the number of functions supported and return it to the + host. For each declared device property, a dataset must be created in the application. + This table is used is the application has not defined any device properties. */ +USHORT _ux_device_class_pima_device_prop_supported[] = { + + UX_DEVICE_CLASS_PIMA_DEV_PROP_UNDEFINED, + UX_DEVICE_CLASS_PIMA_DEV_PROP_BATTERY_LEVEL, + UX_DEVICE_CLASS_PIMA_DEV_PROP_FUNCTIONAL_MODE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_IMAGE_SIZE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_COMPRESSION_SETTING, + UX_DEVICE_CLASS_PIMA_DEV_PROP_WHITE_BALANCE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_RGB_GAIN, + UX_DEVICE_CLASS_PIMA_DEV_PROP_F_NUMBER, + UX_DEVICE_CLASS_PIMA_DEV_PROP_FOCAL_LENGTH, + UX_DEVICE_CLASS_PIMA_DEV_PROP_FOCUS_DISTANCE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_FOCUS_MODE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_EXPOSURE_METERING_MODE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_FLASH_MODE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_EXPOSURE_TIME, + UX_DEVICE_CLASS_PIMA_DEV_PROP_EXPOSURE_PROGRAM_MODE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_EXPOSURE_INDEX, + UX_DEVICE_CLASS_PIMA_DEV_PROP_EXPOSURE_BIAS_COMPENSATION, + UX_DEVICE_CLASS_PIMA_DEV_PROP_DATE_TIME, + UX_DEVICE_CLASS_PIMA_DEV_PROP_CAPTURE_DELAY, + UX_DEVICE_CLASS_PIMA_DEV_PROP_STILL_CAPTURE_MODE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_CONTRAST, + UX_DEVICE_CLASS_PIMA_DEV_PROP_SHARPNESS, + UX_DEVICE_CLASS_PIMA_DEV_PROP_DIGITAL_ZOOM, + UX_DEVICE_CLASS_PIMA_DEV_PROP_EFFECT_MODE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_BURST_NUMBER, + UX_DEVICE_CLASS_PIMA_DEV_PROP_BURST_INTERVAL, + UX_DEVICE_CLASS_PIMA_DEV_PROP_TIME_LAPSE_NUMBER, + UX_DEVICE_CLASS_PIMA_DEV_PROP_TIME_LAPSE_INTERVAL, + UX_DEVICE_CLASS_PIMA_DEV_PROP_FOCUS_METERING_MODE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_UPLOAD_URL, + UX_DEVICE_CLASS_PIMA_DEV_PROP_ARTIST, + UX_DEVICE_CLASS_PIMA_DEV_PROP_COPYRIGHT_INFO, +#ifdef UX_PIMA_WITH_MTP_SUPPORT + UX_DEVICE_CLASS_PIMA_DEV_PROP_SYNCHRONIZATION_PARTNER, + UX_DEVICE_CLASS_PIMA_DEV_PROP_DEVICE_FRIENDLY_NAME, + UX_DEVICE_CLASS_PIMA_DEV_PROP_VOLUME, + UX_DEVICE_CLASS_PIMA_DEV_PROP_SUPPORTED_FORMATS_ORDERED, + UX_DEVICE_CLASS_PIMA_DEV_PROP_DEVICE_ICON, + UX_DEVICE_CLASS_PIMA_DEV_PROP_PLAYBACK_RATE, + UX_DEVICE_CLASS_PIMA_DEV_PROP_PLAYBACK_OBJECT, + UX_DEVICE_CLASS_PIMA_DEV_PROP_PLAYBACK_CONTAINER, + UX_DEVICE_CLASS_PIMA_DEV_PROP_SESSION_INITIATOR_VERSION_INFO, + UX_DEVICE_CLASS_PIMA_DEV_PROP_PERCEIVED_DEVICE_TYPE, +#endif + 0 + }; + +/* Define PIMA supported capture formats. The last entry MUST be a zero. The DeviceInfoSet command + will parse this array and compute the number of functions supported and return it to the + host. + This table is used is the application has not defined any capture formats. */ +USHORT _ux_device_class_pima_supported_capture_formats[] = { + 0 + }; + +/* Define PIMA supported image formats. The last entry MUST be a zero. The DeviceInfoSet command + will parse this array and compute the number of formats supported and return it to the + host. + This table is used is the application has not defined any capture formats. */ +USHORT _ux_device_class_pima_supported_image_formats[] = { + UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED, + UX_DEVICE_CLASS_PIMA_OFC_ASSOCIATION, + UX_DEVICE_CLASS_PIMA_OFC_SCRIPT, + UX_DEVICE_CLASS_PIMA_OFC_EXECUTABLE, + UX_DEVICE_CLASS_PIMA_OFC_TEXT, + UX_DEVICE_CLASS_PIMA_OFC_HTML, + UX_DEVICE_CLASS_PIMA_OFC_DPOF, + UX_DEVICE_CLASS_PIMA_OFC_AIFF, + UX_DEVICE_CLASS_PIMA_OFC_WAV, + UX_DEVICE_CLASS_PIMA_OFC_MP3, + UX_DEVICE_CLASS_PIMA_OFC_AVI, + UX_DEVICE_CLASS_PIMA_OFC_MPEG, + UX_DEVICE_CLASS_PIMA_OFC_ASF, + UX_DEVICE_CLASS_PIMA_OFC_DEFINED, + UX_DEVICE_CLASS_PIMA_OFC_EXIF_JPEG, + UX_DEVICE_CLASS_PIMA_OFC_TIFF_EP, + UX_DEVICE_CLASS_PIMA_OFC_FLASHPIX, + UX_DEVICE_CLASS_PIMA_OFC_BMP, + UX_DEVICE_CLASS_PIMA_OFC_CIFF, + UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED, + UX_DEVICE_CLASS_PIMA_OFC_GIF, + UX_DEVICE_CLASS_PIMA_OFC_JFIF, + UX_DEVICE_CLASS_PIMA_OFC_CD, + UX_DEVICE_CLASS_PIMA_OFC_PICT, + UX_DEVICE_CLASS_PIMA_OFC_PNG, + UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED, + UX_DEVICE_CLASS_PIMA_OFC_TIFF, + UX_DEVICE_CLASS_PIMA_OFC_TIFF_IT, + UX_DEVICE_CLASS_PIMA_OFC_JP2, + UX_DEVICE_CLASS_PIMA_OFC_JPX, +#ifdef UX_PIMA_WITH_MTP_SUPPORT + UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_FIRMWARE, + UX_DEVICE_CLASS_PIMA_OFC_WINDOWS_IMAGE_FORMAT, + UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_AUDIO, + UX_DEVICE_CLASS_PIMA_OFC_WMA, + UX_DEVICE_CLASS_PIMA_OFC_OGG, + UX_DEVICE_CLASS_PIMA_OFC_AAC, + UX_DEVICE_CLASS_PIMA_OFC_AUDIBLE, + UX_DEVICE_CLASS_PIMA_OFC_FLAC, + UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_VIDEO, + UX_DEVICE_CLASS_PIMA_OFC_WMV, + UX_DEVICE_CLASS_PIMA_OFC_MP4_CONTAINER, + UX_DEVICE_CLASS_PIMA_OFC_MP2, + UX_DEVICE_CLASS_PIMA_OFC_3GP_CONTAINER, + UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_COLLECTION, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_MULTIMEDIA_ALBUM, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_IMAGE_ALBUM, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_AUDIO_ALBUM, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_VIDEO_ALBUM, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_AUDIO_AND_VIDEO_PLAYLIST, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_CONTACT_GROUP, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_MESSAGE_FOLDER, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_CHAPTERED_PRODUCTION, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_AUDIO_PLAYLIST, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_VIDEO_PLAYLIST, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_MEDIACAST, + UX_DEVICE_CLASS_PIMA_OFC_WPL_PLAYLIST, + UX_DEVICE_CLASS_PIMA_OFC_M3U_PLAYLIST, + UX_DEVICE_CLASS_PIMA_OFC_MPL_PLAYLIST, + UX_DEVICE_CLASS_PIMA_OFC_ASX_PLAYLIST, + UX_DEVICE_CLASS_PIMA_OFC_PLS_PLAYLIST, + UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_DOCUMENT, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_DOCUMENT, + UX_DEVICE_CLASS_PIMA_OFC_XML_DOCUMENT, + UX_DEVICE_CLASS_PIMA_OFC_MICROSOFT_WORD_DOCUMENT, + UX_DEVICE_CLASS_PIMA_OFC_MHT_COMPILED_HTML_DOCUMENT, + UX_DEVICE_CLASS_PIMA_OFC_MICROSOFT_EXCEL_SPREADSHEET, + UX_DEVICE_CLASS_PIMA_OFC_MICROSOFT_POWERPOINT_PRESENTATION, + UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_MESSAGE, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_MESSAGE, + UX_DEVICE_CLASS_PIMA_OFC_UNDEFINED_CONTACT, + UX_DEVICE_CLASS_PIMA_OFC_ABSTRACT_CONTACT, + UX_DEVICE_CLASS_PIMA_OFC_VCARD2, +#endif + 0 + }; diff --git a/common/usbx_device_classes/src/ux_device_class_pima_deactivate.c b/common/usbx_device_classes/src/ux_device_class_pima_deactivate.c new file mode 100644 index 0000000..63530ef --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_deactivate.c @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivate an instance of the pima class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_all_request_abort Abort all transfers */ +/* */ +/* CALLED BY */ +/* */ +/* PIMA Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_deactivate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_PIMA *pima; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Store the class instance in the container. */ + pima = (UX_SLAVE_CLASS_PIMA *) class -> ux_slave_class_instance; + + /* Terminate the transactions pending on the endpoints. */ + _ux_device_stack_transfer_all_request_abort(pima -> ux_device_class_pima_bulk_in_endpoint, UX_TRANSFER_BUS_RESET); + _ux_device_stack_transfer_all_request_abort(pima -> ux_device_class_pima_bulk_out_endpoint, UX_TRANSFER_BUS_RESET); + _ux_device_stack_transfer_all_request_abort(pima -> ux_device_class_pima_interrupt_endpoint, UX_TRANSFER_BUS_RESET); + + /* Session is now closed. */ + pima -> ux_device_class_pima_session_id = 0; + + /* If there is a deactivate function call it. */ + if (pima -> ux_device_class_pima_instance_deactivate != UX_NULL) + { + /* Invoke the application. */ + pima -> ux_device_class_pima_instance_deactivate(pima); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_DEACTIVATE, pima, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(pima); + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_device_info_send.c b/common/usbx_device_classes/src/ux_device_class_pima_device_info_send.c new file mode 100644 index 0000000..c9decae --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_device_info_send.c @@ -0,0 +1,309 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_device_info_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the device info structure to the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 16-bit value */ +/* _ux_utility_memory_set Set memory */ +/* _ux_utility_string_to_unicode Ascii string to unicode */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_device_info_send(UX_SLAVE_CLASS_PIMA *pima) +{ +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG device_info_length; +UCHAR *device_info; +UCHAR *device_info_pointer; +ULONG array_field_counter; +USHORT *array_pointer; + + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_DEVICE_INFO_SEND, pima, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. We use the transfer request pre-allocated buffer. */ + device_info = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Fill in the data container type. */ + _ux_utility_short_put(device_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(device_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_INFO); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(device_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Allocate the device info pointer to the beginning of the dynamic device info field. */ + device_info_pointer = device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_DESC; + + /* Fill in the standard version field. */ + _ux_utility_short_put(device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_STANDARD_VERSION, + UX_DEVICE_CLASS_PIMA_STANDARD_VERSION); + + /* Fill in the vendor extension ID field. */ + _ux_utility_long_put(device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_ID, + UX_DEVICE_CLASS_PIMA_VENDOR_EXTENSION_ID); + + /* Fill in the vendor extension version. */ + _ux_utility_short_put(device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_VERSION, + UX_DEVICE_CLASS_PIMA_EXTENSION_VERSION); + + /* Fill in the vendor extension description. */ + _ux_utility_string_to_unicode(_ux_device_class_pima_vendor_extension_descriptor, device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_DESC); + + /* Calculate the address of the dynamic area of the device info. */ + device_info_pointer = device_info + UX_DEVICE_CLASS_PIMA_DEVICE_INFO_VENDOR_EXTENSION_DESC; + + /* Update the device info pointer after the Unicode string. */ + device_info_pointer += (ULONG) *(device_info_pointer) * 2 + 1; + + /* Add the functional mode which is set to standard. */ + _ux_utility_short_put(device_info_pointer, UX_DEVICE_CLASS_PIMA_STANDARD_MODE); + + /* Update the device info pointer. */ + device_info_pointer += sizeof(USHORT); + + /* Fill in the supported operations. This table is defined locally. */ + array_field_counter = 0; + while (_ux_device_class_pima_supported_operations[array_field_counter] != 0) + { + /* Add one element. */ + _ux_utility_short_put(device_info_pointer + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter), + _ux_device_class_pima_supported_operations[array_field_counter]); + + /* Next element. */ + array_field_counter++; + + } + + /* Put the length of this variable array at the beginning of the field. */ + _ux_utility_long_put(device_info_pointer, array_field_counter); + + /* Update the device info pointer. */ + device_info_pointer += sizeof(ULONG) + (sizeof(USHORT) * array_field_counter); + + /* Fill in the supported events. This table is defined locally. */ + array_field_counter = 0; + while (_ux_device_class_pima_supported_events[array_field_counter] != 0) + { + /* Add one element. */ + _ux_utility_short_put(device_info_pointer + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter), + _ux_device_class_pima_supported_events[array_field_counter]); + + /* Next element. */ + array_field_counter++; + + } + + /* Put the length of this variable array at the beginning of the field. */ + _ux_utility_long_put(device_info_pointer, array_field_counter); + + /* Update the device info pointer. */ + device_info_pointer += sizeof(ULONG) + (sizeof(USHORT) * array_field_counter); + + /* Fill in the supported properties. This table can be configured by the user. If it is declared NULL, use the local default one. */ + array_pointer = pima -> ux_device_class_pima_device_properties_list; + + /* Check if array defined. */ + if (array_pointer == UX_NULL) + + /* Use local array. */ + array_pointer = _ux_device_class_pima_device_prop_supported; + + /* Reset counter. */ + array_field_counter = 0; + + /* Parse the table. */ + while (*(array_pointer + array_field_counter) != 0) + { + /* Add one element. */ + _ux_utility_short_put(device_info_pointer + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter), + *(array_pointer + array_field_counter)); + + /* Next element. */ + array_field_counter++; + + } + + /* Put the length of this variable array at the beginning of the field. */ + _ux_utility_long_put(device_info_pointer, array_field_counter); + + /* Update the device info pointer. */ + device_info_pointer += sizeof(ULONG) + (sizeof(USHORT) * array_field_counter); + + /* Fill in the supported capture formats. This table can be configured by the user. If it is declared NULL, use the local default one. */ + array_pointer = pima -> ux_device_class_pima_supported_capture_formats_list; + + /* Check if array defined. */ + if (array_pointer == UX_NULL) + + /* Use local array. */ + array_pointer = _ux_device_class_pima_supported_capture_formats; + + /* Reset counter. */ + array_field_counter = 0; + + /* Parse the table. */ + while (*(array_pointer + array_field_counter) != 0) + { + /* Add one element. */ + _ux_utility_short_put(device_info_pointer + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter), + *(array_pointer + array_field_counter)); + + /* Next element. */ + array_field_counter++; + + } + + /* Put the length of this variable array at the beginning of the field. */ + _ux_utility_long_put(device_info_pointer, array_field_counter); + + /* Update the device info pointer. */ + device_info_pointer += sizeof(ULONG) + (sizeof(USHORT) * array_field_counter); + + /* Fill in the supported image formats. This table can be configured by the user. If it is declared NULL, use the local default one. */ + array_pointer = pima -> ux_device_class_pima_supported_image_formats_list; + + /* Check if array defined. */ + if (array_pointer == UX_NULL) + + /* Use local array. */ + array_pointer = _ux_device_class_pima_supported_image_formats; + + /* Reset counter. */ + array_field_counter = 0; + + /* Parse the table. */ + while (*(array_pointer + array_field_counter) != 0) + { + /* Add one element. */ + _ux_utility_short_put(device_info_pointer + sizeof(ULONG) + (sizeof(USHORT) * array_field_counter), + *(array_pointer + array_field_counter)); + + /* Next element. */ + array_field_counter++; + + } + + /* Put the length of this variable array at the beginning of the field. */ + _ux_utility_long_put(device_info_pointer, array_field_counter); + + /* Update the device info pointer. */ + device_info_pointer += sizeof(ULONG) + (sizeof(USHORT) * array_field_counter); + + /* Fill in the manufacturer string. */ + _ux_utility_string_to_unicode(pima -> ux_device_class_pima_manufacturer, device_info_pointer); + + /* Update the device info pointer. */ + device_info_pointer += (ULONG) (*device_info_pointer * 2) + 1; + + /* Fill in the model string. */ + _ux_utility_string_to_unicode(pima -> ux_device_class_pima_model, device_info_pointer); + + /* Update the device info pointer. */ + device_info_pointer += (ULONG) (*device_info_pointer * 2) + 1; + + /* Fill in the device version string. */ + _ux_utility_string_to_unicode(pima -> ux_device_class_pima_device_version, device_info_pointer); + + /* Update the device info pointer. */ + device_info_pointer += (ULONG) (*device_info_pointer * 2) + 1; + + /* Fill in the device serial number. */ + _ux_utility_string_to_unicode(pima -> ux_device_class_pima_serial_number, device_info_pointer); + + /* Update the device info pointer. */ + device_info_pointer += (ULONG) (*device_info_pointer * 2) + 1; + + /* Compute the overall length of the device info structure. */ + device_info_length = (ULONG) ((ALIGN_TYPE) device_info_pointer - (ALIGN_TYPE) device_info); + + /* Set the transfer data pointer. */ + transfer_request -> ux_slave_transfer_request_data_pointer = device_info; + + /* Fill in the size of the response header. */ + _ux_utility_long_put(device_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + device_info_length); + + /* Send a data payload with the device info data set. */ + status = _ux_device_stack_transfer_request(transfer_request, device_info_length, 0); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_device_prop_desc_get.c b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_desc_get.c new file mode 100644 index 0000000..173e517 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_desc_get.c @@ -0,0 +1,156 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_device_prop_desc_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Return an Device Property Description dataset. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* device_property_code Device Property code for */ +/* which the dataset is obtained */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_short_put Put 16-bit value */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_device_prop_desc_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG device_property_code) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *pima_data_buffer; +ULONG device_property_desc_dataset_length; +UCHAR *device_property_desc_dataset; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_GET_DEVICE_PROP_DESC_GET, pima, device_property_code, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + pima_data_buffer = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Fill in the data container type. */ + _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_PROP_DESC); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Ask the application to retrieve for us the device prop description. */ + status = pima -> ux_device_class_pima_device_prop_desc_get(pima, device_property_code, &device_property_desc_dataset, &device_property_desc_dataset_length); + + /* Result should always be OK, but to be sure .... */ + if (status != UX_SUCCESS) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_DEVICE_PROP_NOT_SUPPORTED, 0, 0, 0, 0); + + else + { + + /* Ensure the application's data can fit in the endpoint's data buffer. */ + if (device_property_desc_dataset_length + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE > UX_SLAVE_REQUEST_DATA_MAX_LENGTH) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR, 0, 0, 0, 0); + + /* Return overflow error. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Copy the property dataset into the local buffer. */ + _ux_utility_memory_copy(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, device_property_desc_dataset, device_property_desc_dataset_length); + + /* Add the header size to the payload. */ + device_property_desc_dataset_length += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Fill in the size of the response header. */ + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + device_property_desc_dataset_length); + + /* Send a data payload with the device prop description dataset. */ + status = _ux_device_stack_transfer_request(transfer_request, device_property_desc_dataset_length, 0); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + } + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_get.c b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_get.c new file mode 100644 index 0000000..c4a21a4 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_get.c @@ -0,0 +1,142 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_device_prop_value_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Return an Device Property Value. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* device_property_code Device Property code for */ +/* which the value is obtained. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_short_put Put 16-bit value */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_device_prop_value_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG device_property_code) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *pima_data_buffer; +ULONG device_property_value_length; +UCHAR *device_property_value; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_GET_DEVICE_PROP_VALUE, pima, device_property_code, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + pima_data_buffer = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Fill in the data container type. */ + _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_PROP_VALUE); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Ask the application to retrieve for us the device prop value. */ + status = pima -> ux_device_class_pima_device_prop_value_get(pima, device_property_code, &device_property_value, &device_property_value_length); + + /* Result should always be OK, but to be sure .... */ + if (status != UX_SUCCESS) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); + + else + { + + /* Copy the property dataset into the local buffer. */ + _ux_utility_memory_copy(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, device_property_value, device_property_value_length); + + /* Add the header size to the payload. */ + device_property_value_length += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Fill in the size of the response header. */ + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + device_property_value_length); + + /* Send a data payload with the device prop value. */ + status = _ux_device_stack_transfer_request(transfer_request, device_property_value_length, 0); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + } + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_set.c b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_set.c new file mode 100644 index 0000000..702744b --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_device_prop_value_set.c @@ -0,0 +1,139 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_device_prop_value_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives an device object value from the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_device_prop_value_set(UX_SLAVE_CLASS_PIMA *pima, ULONG device_property_code) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *device_property_value; +ULONG device_property_value_length; +UCHAR *device_property_value_pointer; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_GET_DEVICE_PROP_VALUE_SET, pima, device_property_code, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_out_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + device_property_value = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Get the data payload. */ + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_PIMA_DEVICE_PROP_VALUE_BUFFER_SIZE, + UX_DEVICE_CLASS_PIMA_DEVICE_PROP_VALUE_BUFFER_SIZE); + + /* Check if there was an error. If so, stall the endpoint. */ + if (status != UX_SUCCESS) + { + + /* Stall the endpoint. */ + _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_out_endpoint); + + /* Return the status. */ + return(status); + + } + + /* Allocate the device info pointer to the beginning of the dynamic object info field. */ + device_property_value_pointer = device_property_value + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Obtain the length of the data payload. */ + device_property_value_length = transfer_request -> ux_slave_transfer_request_actual_length; + + /* Ensure there is some data payload. */ + if (device_property_value_length > UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE) + { + + /* Take out the header. */ + device_property_value_length -= UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Send the object to the application. */ + status = pima -> ux_device_class_pima_device_prop_value_set(pima, device_property_code, device_property_value_pointer, device_property_value_length); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + } + else + { + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); + + /* Status error. */ + status = UX_ERROR; + + } + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_device_reset.c b/common/usbx_device_classes/src/ux_device_class_pima_device_reset.c new file mode 100644 index 0000000..3a9c162 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_device_reset.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_device_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function informs the application that the device needs to */ +/* be reset. This will close the session. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_device_reset(UX_SLAVE_CLASS_PIMA *pima) +{ + +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_DEVICE_RESET, pima, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Invoke the application callback function. */ + status = pima -> ux_device_class_pima_device_reset(pima); + + /* Check for error. */ + if (status != UX_SUCCESS) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); + + else + { + + /* We return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + /* Session is now closed. */ + pima -> ux_device_class_pima_session_id = 0; + + } + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_entry.c b/common/usbx_device_classes/src/ux_device_class_pima_entry.c new file mode 100644 index 0000000..380e987 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_entry.c @@ -0,0 +1,138 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_class_device_pima_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the pima class. It */ +/* will be called by the device stack enumeration module when the */ +/* host has sent a SET_CONFIGURATION command and the pima interface */ +/* needs to be mounted. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_pima_initialize Initialize pima class */ +/* _ux_device_class_pima_activate Activate pima class */ +/* _ux_device_class_pima_deactivate Deactivate pima class */ +/* _ux_device_class_pima_control_request Request control */ +/* */ +/* CALLED BY */ +/* */ +/* PIMA Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_entry(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_slave_class_command_request) + { + + case UX_SLAVE_CLASS_COMMAND_INITIALIZE: + + /* Call the init function of the PIMA class. */ + status = _ux_device_class_pima_initialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_QUERY: + + /* Check the CLASS definition in the interface descriptor. */ + if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_PIMA_CLASS) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_SLAVE_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the host has sent a SET_CONFIGURATION command + and this interface has to be mounted. Both Bulk endpoints have to be mounted + and the pima thread needs to be activated. */ + status = _ux_device_class_pima_activate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted. + The device endpoints have to be dismounted and the pima thread canceled. */ + status = _ux_device_class_pima_deactivate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_REQUEST: + + /* The request command is used when the host sends a command on the control endpoint. */ + status = _ux_device_class_pima_control_request(command); + + /* Return the completion status. */ + return(status); + + default: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_event_get.c b/common/usbx_device_classes/src/ux_device_class_pima_event_get.c new file mode 100644 index 0000000..5d83d7d --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_event_get.c @@ -0,0 +1,112 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_event_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks if there is an event from the application */ +/* */ +/* INPUT */ +/* */ +/* pima Address of pima class */ +/* event Pointer of the event */ +/* */ +/* OUTPUT */ +/* */ +/* status UX_SUCCESS if there is an */ +/* event */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_event_get(UX_SLAVE_CLASS_PIMA *pima, + UX_SLAVE_CLASS_PIMA_EVENT *pima_event) +{ + +UX_SLAVE_CLASS_PIMA_EVENT *current_pima_event; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_EVENT_GET, pima, pima_event, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Check if the head and the tail of the event array is the same. */ + if (pima -> ux_device_class_pima_event_array_head == + pima -> ux_device_class_pima_event_array_tail) + + /* No event to report. */ + return(UX_ERROR); + + /* There is an event to report, get the current pointer to the event. */ + current_pima_event = pima -> ux_device_class_pima_event_array_tail; + + /* fill in the event structure from the user. */ + pima_event -> ux_device_class_pima_event_code = current_pima_event -> ux_device_class_pima_event_code; + pima_event -> ux_device_class_pima_event_session_id = pima -> ux_device_class_pima_session_id; + pima_event -> ux_device_class_pima_event_transaction_id = pima -> ux_device_class_pima_transaction_id; + pima_event -> ux_device_class_pima_event_parameter_1 = current_pima_event -> ux_device_class_pima_event_parameter_1; + pima_event -> ux_device_class_pima_event_parameter_2 = current_pima_event -> ux_device_class_pima_event_parameter_2; + pima_event -> ux_device_class_pima_event_parameter_3 = current_pima_event -> ux_device_class_pima_event_parameter_3; + + + /* Adjust the tail pointer. Check if we are at the end. */ + if ((current_pima_event + 1) == pima -> ux_device_class_pima_event_array_end) + + /* We are at the end, go back to the beginning. */ + pima -> ux_device_class_pima_event_array_tail = pima -> ux_device_class_pima_event_array; + + else + /* We are not at the end, increment the tail position. */ + pima -> ux_device_class_pima_event_array_tail++; + + + /* Return event status to the user. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_event_set.c b/common/usbx_device_classes/src/ux_device_class_pima_event_set.c new file mode 100644 index 0000000..b360979 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_event_set.c @@ -0,0 +1,135 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_event_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends an event to the pima class. It is processed */ +/* asynchronously by the interrupt thread. */ +/* */ +/* INPUT */ +/* */ +/* pima Address of pima class */ +/* event Pointer of the event */ +/* */ +/* OUTPUT */ +/* */ +/* status UX_SUCCESS if there is an */ +/* event */ +/* CALLS */ +/* */ +/* _ux_utility_semaphore_put Put semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_event_set(UX_SLAVE_CLASS_PIMA *pima, + UX_SLAVE_CLASS_PIMA_EVENT *pima_event) +{ + +UX_SLAVE_CLASS_PIMA_EVENT *current_pima_event; +UX_SLAVE_CLASS_PIMA_EVENT *next_pima_event; +UX_SLAVE_DEVICE *device; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_EVENT_SET, pima, pima_event, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Check the device state. */ + if (device -> ux_slave_device_state != UX_DEVICE_CONFIGURED) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_HANDLE_UNKNOWN, device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DEVICE_HANDLE_UNKNOWN); + } + + /* Current position of the head. */ + current_pima_event = pima -> ux_device_class_pima_event_array_head; + + /* If the pointer is NULL, the round robin buffer has not been activated. */ + if (current_pima_event == UX_NULL) + return (UX_ERROR); + + /* Calculate the next position. */ + if ((current_pima_event + 1) == pima -> ux_device_class_pima_event_array_end) + + /* We are at the end, go back to the beginning. */ + next_pima_event = pima -> ux_device_class_pima_event_array; + + else + /* We are not at the end, increment the head position. */ + next_pima_event = current_pima_event + 1; + + + /* Any place left for this event ? */ + if (next_pima_event == pima -> ux_device_class_pima_event_array_tail) + return (UX_ERROR); + + /* Update the head. */ + pima -> ux_device_class_pima_event_array_head = next_pima_event; + + /* There is an event to report, get the current pointer to the event. */ + current_pima_event = pima -> ux_device_class_pima_event_array_tail; + + /* fill in the event structure from the user. */ + current_pima_event -> ux_device_class_pima_event_code = pima_event -> ux_device_class_pima_event_code; + current_pima_event -> ux_device_class_pima_event_parameter_1 = pima_event -> ux_device_class_pima_event_parameter_1; + current_pima_event -> ux_device_class_pima_event_parameter_2 = pima_event -> ux_device_class_pima_event_parameter_2; + current_pima_event -> ux_device_class_pima_event_parameter_3 = pima_event -> ux_device_class_pima_event_parameter_3; + + /* Set a semaphore to wake up the interrupt thread. */ + _ux_utility_semaphore_put(&pima -> ux_device_class_pima_interrupt_thread_semaphore); + + /* Return event status to the user. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_initialize.c b/common/usbx_device_classes/src/ux_device_class_pima_initialize.c new file mode 100644 index 0000000..9afd7c4 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_initialize.c @@ -0,0 +1,215 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB Pima device class */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to pima command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_thread_create Create thread */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_initialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; +UX_SLAVE_CLASS_PIMA *pima; +UX_SLAVE_CLASS_PIMA_PARAMETER *pima_parameter; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Create an instance of the device pima class. */ + pima = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_PIMA)); + + /* Check for successful allocation. */ + if (pima == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save the address of the PIMA instance inside the PIMA container. */ + class -> ux_slave_class_instance = (VOID *) pima; + + /* Allocate some memory for the thread stack. */ + class -> ux_slave_class_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (class -> ux_slave_class_thread_stack == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + else + status = UX_SUCCESS; + + /* This instance needs to be running in a different thread. So start + a new thread. We pass a pointer to the class to the new thread. This thread + does not start until we have a instance of the class. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_thread_create(&class -> ux_slave_class_thread, "ux_slave_class_thread", + _ux_device_class_pima_thread, + (ULONG) (ALIGN_TYPE) class, (VOID *) class -> ux_slave_class_thread_stack, + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_DONT_START); + + /* Check the creation of this thread. */ + if (status != UX_SUCCESS) + status = UX_THREAD_ERROR; + } + + UX_THREAD_EXTENSION_PTR_SET(&(class -> ux_slave_class_thread), class) + + /* There is error, free resources and return error. */ + if (status != UX_SUCCESS) + { + + /* The last resource, thread is not created or created error, + no need to free. */ + + if (class -> ux_slave_class_thread_stack) + _ux_utility_memory_free(class -> ux_slave_class_thread_stack); + + /* Detach instance and free memory. */ + class -> ux_slave_class_instance = UX_NULL; + _ux_utility_memory_free(pima); + + /* Return completion status. */ + return(status); + } + + /* Success, complete remaining settings. */ + + /* Get the pointer to the application parameters for the pima class. */ + pima_parameter = command -> ux_slave_class_command_parameter; + + /* Store all the application parameter information about the media. */ + pima -> ux_device_class_pima_manufacturer = pima_parameter -> ux_device_class_pima_parameter_manufacturer; + pima -> ux_device_class_pima_model = pima_parameter -> ux_device_class_pima_parameter_model; + pima -> ux_device_class_pima_device_version = pima_parameter -> ux_device_class_pima_parameter_device_version; + pima -> ux_device_class_pima_serial_number = pima_parameter -> ux_device_class_pima_parameter_serial_number; + + /* Store all the application parameter information about the storage. */ + pima -> ux_device_class_pima_storage_id = pima_parameter -> ux_device_class_pima_parameter_storage_id; + pima -> ux_device_class_pima_storage_type = pima_parameter -> ux_device_class_pima_parameter_storage_type; + pima -> ux_device_class_pima_storage_file_system_type = pima_parameter -> ux_device_class_pima_parameter_storage_file_system_type; + pima -> ux_device_class_pima_storage_access_capability = pima_parameter -> ux_device_class_pima_parameter_storage_access_capability; + pima -> ux_device_class_pima_storage_max_capacity_low = pima_parameter -> ux_device_class_pima_parameter_storage_max_capacity_low; + pima -> ux_device_class_pima_storage_max_capacity_high = pima_parameter -> ux_device_class_pima_parameter_storage_max_capacity_high; + pima -> ux_device_class_pima_storage_free_space_low = pima_parameter -> ux_device_class_pima_parameter_storage_free_space_low; + pima -> ux_device_class_pima_storage_free_space_high = pima_parameter -> ux_device_class_pima_parameter_storage_free_space_high; + pima -> ux_device_class_pima_storage_free_space_image = pima_parameter -> ux_device_class_pima_parameter_storage_free_space_image; + pima -> ux_device_class_pima_storage_description = pima_parameter -> ux_device_class_pima_parameter_storage_description; + pima -> ux_device_class_pima_storage_volume_label = pima_parameter -> ux_device_class_pima_parameter_storage_volume_label; + + /* Update device properties supported. */ + pima -> ux_device_class_pima_device_properties_list = pima_parameter -> ux_device_class_pima_parameter_device_properties_list; + + /* Update the capture formats supported list. */ + pima -> ux_device_class_pima_supported_capture_formats_list = pima_parameter -> ux_device_class_pima_parameter_supported_capture_formats_list; + + /* Update the image formats supported list. */ + pima -> ux_device_class_pima_supported_image_formats_list = pima_parameter -> ux_device_class_pima_parameter_supported_image_formats_list; + +#ifdef UX_PIMA_WITH_MTP_SUPPORT + /* Update the internal pima structure with the object properties. */ + pima -> ux_device_class_pima_object_properties_list = pima_parameter -> ux_device_class_pima_parameter_object_properties_list; + +#endif + + /* Store the callback functions for device. */ + pima -> ux_device_class_pima_device_reset = pima_parameter -> ux_device_class_pima_parameter_device_reset; + pima -> ux_device_class_pima_device_prop_desc_get = pima_parameter -> ux_device_class_pima_parameter_device_prop_desc_get; + pima -> ux_device_class_pima_device_prop_value_get = pima_parameter -> ux_device_class_pima_parameter_device_prop_value_get; + pima -> ux_device_class_pima_device_prop_value_set = pima_parameter -> ux_device_class_pima_parameter_device_prop_value_set; + + /* Store the callback functions for storage. */ + pima -> ux_device_class_pima_storage_format = pima_parameter -> ux_device_class_pima_parameter_storage_format; + pima -> ux_device_class_pima_storage_info_get = pima_parameter -> ux_device_class_pima_parameter_storage_info_get; + + /* Store the callback functions for objects. */ + pima -> ux_device_class_pima_object_number_get = pima_parameter -> ux_device_class_pima_parameter_object_number_get; + pima -> ux_device_class_pima_object_handles_get = pima_parameter -> ux_device_class_pima_parameter_object_handles_get; + pima -> ux_device_class_pima_object_info_get = pima_parameter -> ux_device_class_pima_parameter_object_info_get; + pima -> ux_device_class_pima_object_data_get = pima_parameter -> ux_device_class_pima_parameter_object_data_get; + pima -> ux_device_class_pima_object_info_send = pima_parameter -> ux_device_class_pima_parameter_object_info_send; + pima -> ux_device_class_pima_object_data_send = pima_parameter -> ux_device_class_pima_parameter_object_data_send; + pima -> ux_device_class_pima_object_delete = pima_parameter -> ux_device_class_pima_parameter_object_delete; + + +#ifdef UX_PIMA_WITH_MTP_SUPPORT + /* Add the MTP specific callback functions. */ + pima -> ux_device_class_pima_object_prop_desc_get = pima_parameter -> ux_device_class_pima_parameter_object_prop_desc_get; + pima -> ux_device_class_pima_object_prop_value_get = pima_parameter -> ux_device_class_pima_parameter_object_prop_value_get; + pima -> ux_device_class_pima_object_prop_value_set = pima_parameter -> ux_device_class_pima_parameter_object_prop_value_set; + pima -> ux_device_class_pima_object_references_get = pima_parameter -> ux_device_class_pima_parameter_object_references_get; + pima -> ux_device_class_pima_object_references_set = pima_parameter -> ux_device_class_pima_parameter_object_references_set; +#endif + + /* Store the application owner. */ + pima -> ux_device_class_pima_application = pima_parameter -> ux_device_class_pima_parameter_application; + + /* Store the start and stop signals if needed by the application. */ + pima -> ux_device_class_pima_instance_activate = pima_parameter -> ux_device_class_pima_instance_activate; + pima -> ux_device_class_pima_instance_deactivate = pima_parameter -> ux_device_class_pima_instance_deactivate; + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_interrupt_thread.c b/common/usbx_device_classes/src/ux_device_class_pima_interrupt_thread.c new file mode 100644 index 0000000..1f2f1ae --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_interrupt_thread.c @@ -0,0 +1,175 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_interrupt_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the pima interrupt endpoint */ +/* */ +/* INPUT */ +/* */ +/* pima_class Address of pima class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_device_class_pima_event_get Get PIMA event */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 16-bit value */ +/* _ux_utility_thread_suspend Suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_pima_interrupt_thread(ULONG pima_class) +{ + +UX_SLAVE_CLASS_PIMA *pima; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request_in; +UX_SLAVE_CLASS_PIMA_EVENT pima_event; +UINT status; +UCHAR *buffer; + + /* Get the pima instance from the calling parameter. */ + UX_THREAD_EXTENSION_PTR_GET(pima, UX_SLAVE_CLASS_PIMA, pima_class) + + /* Allocate the event round robin buffer. */ + pima -> ux_device_class_pima_event_array = + _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_PIMA_EVENT), UX_DEVICE_CLASS_PIMA_MAX_EVENTS_QUEUE); + + /* Check for successful allocation. */ + if (pima -> ux_device_class_pima_event_array == UX_NULL) + { + /* Return, no event management. */ + return; + } + + /* Allocate the head\tail and end of the round robin buffer. */ + pima -> ux_device_class_pima_event_array_head = pima -> ux_device_class_pima_event_array; + pima -> ux_device_class_pima_event_array_tail = pima -> ux_device_class_pima_event_array; + pima -> ux_device_class_pima_event_array_end = pima -> ux_device_class_pima_event_array + UX_DEVICE_CLASS_PIMA_MAX_EVENTS_QUEUE; + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* All PIMA events are on the interrupt endpoint IN, from the host. */ + transfer_request_in = &pima -> ux_device_class_pima_interrupt_endpoint -> ux_slave_endpoint_transfer_request; + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Wait until something has awaken us. */ + status = _ux_utility_semaphore_get(&pima -> ux_device_class_pima_interrupt_thread_semaphore, UX_WAIT_FOREVER); + + /* Check the completion code. */ + if (status != UX_SUCCESS) + + /* Do not proceed. */ + return; + + /* Check if we have an event to report. */ + status = _ux_device_class_pima_event_get(pima, &pima_event); + + /* We may have an event to report on the interrupt pipe. */ + if(status == UX_SUCCESS) + { + + /* Prepare the event data payload from the pima event structure. Get a pointer to the buffer area. */ + buffer = transfer_request_in -> ux_slave_transfer_request_data_pointer; + + /* Put the length of the entire event payload. */ + _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_DATA_LENGTH, UX_DEVICE_CLASS_PIMA_AEI_MAX_LENGTH); + + /* Put the type of packet (Event) */ + _ux_utility_short_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_TYPE, UX_DEVICE_CLASS_PIMA_CT_EVENT_BLOCK); + + /* Put the type of event. */ + _ux_utility_short_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_EVENT_CODE, (USHORT)pima_event.ux_device_class_pima_event_code); + + /* Put the transaction ID. */ + _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_TRANSACTION_ID, 0xFFFFFFFF); + + /* Put the value of parameter 1. */ + _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_1, pima_event.ux_device_class_pima_event_parameter_1); + + /* Put the value of parameter 2. */ + _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_2, pima_event.ux_device_class_pima_event_parameter_3); + + /* Put the value of parameter 3. */ + _ux_utility_long_put(buffer + UX_DEVICE_CLASS_PIMA_AEI_PARAMETER_2, pima_event.ux_device_class_pima_event_parameter_3); + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request_in, UX_DEVICE_CLASS_PIMA_AEI_MAX_LENGTH + 1, UX_DEVICE_CLASS_PIMA_AEI_MAX_LENGTH); + + /* Check error code. */ + if (status != UX_SUCCESS) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + + } + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ + _ux_utility_thread_suspend(&pima -> ux_device_class_pima_interrupt_thread); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_add.c b/common/usbx_device_classes/src/ux_device_class_pima_object_add.c new file mode 100644 index 0000000..cfb604c --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_add.c @@ -0,0 +1,98 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_add PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends an event to the host to inform that an object */ +/* has been added. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* object_handle Handle of object to delete */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_pima_event_set Add PIMA event to queue */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_add(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle) +{ + +UINT status; +UX_SLAVE_CLASS_PIMA_EVENT pima_event; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_ADD, pima, object_handle, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Set the pima code for object added. */ + pima_event.ux_device_class_pima_event_code = UX_DEVICE_CLASS_PIMA_EC_REQUEST_OBJECT_TRANSFER; + + /* Set the object handle. */ + pima_event.ux_device_class_pima_event_parameter_1 = object_handle; + + /* Other parameters are not used. */ + pima_event.ux_device_class_pima_event_parameter_2 = 0; + pima_event.ux_device_class_pima_event_parameter_3 = 0; + + /* Add the event. */ + status = _ux_device_class_pima_event_set(pima, &pima_event); + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_data_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_data_get.c new file mode 100644 index 0000000..4786563 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_data_get.c @@ -0,0 +1,287 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_data_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the object data to the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_data_get(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_CLASS_PIMA_OBJECT *object; +UCHAR *object_data; +ULONG object_offset; +ULONG object_length; +ULONG total_length; +ULONG object_length_demanded; +ULONG object_length_received; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_DATA_GET, pima, object_handle, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the object info from the application. */ + status = pima -> ux_device_class_pima_object_info_get(pima, object_handle, &object); + + /* Check for error. */ + if (status == UX_SUCCESS) + { + + /* Set the object length. */ + object_length = object -> ux_device_class_pima_object_compressed_size; + /* Set the total length to be sent. */ + total_length = object_length + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Reset the offset. */ + object_offset = 0; + + /* Obtain the pointer to the transfer request of the bulk in endpoint. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + object_data = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Fill in the total length to be sent (header + payload. */ + _ux_utility_long_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + total_length); + + /* Fill in the data container type. */ + _ux_utility_short_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Assuming the host will ask for the entire object. */ + while (object_length != 0) + { + + /* If this is the first packet, we have to take into account the + header. */ + if (object_offset == 0) + { + + /* Calculate the maximum length for the first packet. */ + object_length_demanded = UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE - + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Can we get that much from the application ? */ + if (object_length_demanded > object_length) + + /* We ask too much. */ + object_length_demanded = object_length; + + /* Obtain some data from the application. */ + status = pima -> ux_device_class_pima_object_data_get(pima, object_handle, object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, + object_offset, + object_length_demanded, + &object_length_received); + + /* Check status, if we have a problem, we abort. */ + if (status != UX_SUCCESS) + { + + /* We need to inform the host of an error. */ + status = UX_ERROR; + break; + } + else + { + /* Adjust the length of the object. */ + object_length -= object_length_received; + + /* Adjust the offset within the object data. */ + object_offset += object_length_received; + + /* Adjust the length to be sent. */ + object_length_received += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + } + + } + else + { + + /* Calculate the maximum length for the first packet. */ + object_length_demanded = UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE; + + /* Can we get that much from the application ? */ + if (object_length_demanded > object_length) + + /* We ask too much. */ + object_length_demanded = object_length; + + /* Obtain some data from the application. */ + status = pima -> ux_device_class_pima_object_data_get(pima, object_handle, object_data, object_offset, + object_length_demanded, + &object_length_received); + + + + /* Check status, if we have a problem, we abort. */ + if (status != UX_SUCCESS) + { + + /* We need to inform the host of an error. */ + status = UX_ERROR; + break; + + } + + else + { + + /* Adjust the length of the object. */ + object_length -= object_length_received; + /* Adjust the offset within the object data. */ + object_offset += object_length_received; + + } + + } + + /* Check if it is the last transfer. */ + if (object_length > 0) + + /* Not the last transfer, just send the object data to the host. */ + status = _ux_device_stack_transfer_request(transfer_request, object_length_received, object_length_received); + + else + + /* It's the last transfer, we need to send a ZLP if the last packet is a full packet. */ + status = _ux_device_stack_transfer_request(transfer_request, object_length_received, 0); + + /* Check for the status. We may have had a request to cancel the transaction from the host. */ + if (status != UX_SUCCESS) + { + + /* Check the completion code for transfer abort from the host. */ + if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_ABORT) + { + + /* Do not proceed. */ + return(UX_ERROR); + + } + + else + + { + + /* We need to inform the host of an error. */ + status = UX_ERROR; + break; + + } + } + + else + + { + + /* Do some sanity check. */ + if (total_length < object_length_received) + { + /* We have an overflow. Do not proceed. */ + status = UX_ERROR; + break; + + } + + + + /* Update the total length to be sent. */ + total_length -= object_length_received; + + } + } + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + } + + /* Check if status is OK. */ + if (status != UX_SUCCESS) + + /* We need to stall the bulk in pipe. This is the method used by Pima devices to + cancel a transaction. */ + _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_in_endpoint); + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_data_send.c b/common/usbx_device_classes/src/ux_device_class_pima_object_data_send.c new file mode 100644 index 0000000..50472ab --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_data_send.c @@ -0,0 +1,254 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_data_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function accepts an object data from the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_data_send(UX_SLAVE_CLASS_PIMA *pima) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG transfer_length; +UX_SLAVE_CLASS_PIMA_OBJECT *object; +ULONG object_handle; +UCHAR *object_data; +ULONG object_offset; +ULONG object_length; +ULONG total_length; + + /* Get the last object handle. The handle used is the last handle used when he host performed a OBJECT_INFO_SEND. */ + object_handle = pima -> ux_device_class_pima_current_object_handle; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_DATA_SEND, pima, object_handle, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the object info from the application. */ + status = pima -> ux_device_class_pima_object_info_get(pima, object_handle, &object); + + /* Check for error. */ + if (status == UX_SUCCESS) + { + + /* Set the object length. */ + object_length = object -> ux_device_class_pima_object_compressed_size; + + /* Set the total length to be received. */ + total_length = object_length + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Reset the offset. */ + object_offset = 0; + + /* Obtain the pointer to the transfer request of the bulk out endpoint. */ + transfer_request = &pima -> ux_device_class_pima_bulk_out_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + object_data = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Assume the host will send all the data. */ + while (total_length != 0) + { + + /* Get a data payload. */ + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE, UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE); + + /* Check for the status. We may have had a request to cancel the transaction from the host. */ + if (status != UX_SUCCESS) + { + + /* Check the completion code for transfer abort from the host. */ + if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_ABORT) + { + + /* Do not proceed. */ + return(UX_ERROR); + + } + + else + { + /* We have a transmission error. Do not proceed. */ + status = UX_ERROR; + break; + + } + + } + + /* Obtain the length of the transaction. */ + transfer_length = transfer_request -> ux_slave_transfer_request_actual_length; + + /* If this is the first packet, we have to take into account the + header. */ + if (object_offset == 0) + { + + /* Do some sanity check. */ + if (object_length < (transfer_length - UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE)) + { + /* We have an overflow. Do not proceed. */ + status = UX_ERROR; + break; + + } + + /* Send the object data to the application. */ + status = pima -> ux_device_class_pima_object_data_send(pima, object_handle, UX_DEVICE_CLASS_PIMA_OBJECT_TRANSFER_PHASE_ACTIVE, + object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, + object_offset, + (transfer_length - UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE)); + + /* Check status, if we have a problem, we abort. */ + if (status != UX_SUCCESS) + { + + /* We need to inform the host of an error. */ + status = UX_ERROR; + break; + } + else + { + + /* Adjust the remaining length of the object. */ + total_length -= transfer_length; + + /* Adjust the length to be sent. */ + object_offset += (transfer_length - UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE); + + } + + } + else + { + + /* Do some sanity check. */ + if (object_length < (transfer_length - UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE)) + { + /* We have an overflow. Do not proceed. */ + status = UX_ERROR; + break; + + } + + /* This is not the first packet, send the object data to the application. */ + status = pima -> ux_device_class_pima_object_data_send(pima, object_handle, UX_DEVICE_CLASS_PIMA_OBJECT_TRANSFER_PHASE_ACTIVE, + object_data, + object_offset, + transfer_length); + + /* Check status, if we have a problem, we abort. */ + if (status != UX_SUCCESS) + { + + /* We need to inform the host of an error. */ + status = UX_ERROR; + break; + } + else + { + + /* Adjust the remaining length of the total object. */ + total_length -= transfer_length; + + /* Adjust the length to be sent. */ + object_offset += transfer_length; + + } + + } + } + } + + /* Check for status. */ + if (status == UX_SUCCESS) + { + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + /* Make the object transfer completed. */ + status = pima -> ux_device_class_pima_object_data_send(pima, object_handle, UX_DEVICE_CLASS_PIMA_OBJECT_TRANSFER_PHASE_COMPLETED, + UX_NULL, 0, 0); + } + else + { + + /* We need to stall the bulk out pipe. This is the method used by Pima devices to + cancel a transaction. */ + _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_in_endpoint); + + /* Make the object transfer non completed. */ + status = pima -> ux_device_class_pima_object_data_send(pima, object_handle, UX_DEVICE_CLASS_PIMA_OBJECT_TRANSFER_PHASE_COMPLETED_ERROR, + UX_NULL, 0, 0); + + } + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_delete.c b/common/usbx_device_classes/src/ux_device_class_pima_object_delete.c new file mode 100644 index 0000000..e5b9519 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_delete.c @@ -0,0 +1,98 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_delete PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function informs the application that an object is to be */ +/* deleted. The handle points to an object or all objects if -1 */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* object_handle Handle of object to delete */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_delete(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle) +{ + +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_DELETE, pima, object_handle, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Invoke the application callback function. */ + status = pima -> ux_device_class_pima_object_delete(pima, object_handle); + + /* Check for error. */ + if (status != UX_SUCCESS) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_HANDLE, 0, 0, 0, 0); + + else + + /* We return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_handles_send.c b/common/usbx_device_classes/src/ux_device_class_pima_object_handles_send.c new file mode 100644 index 0000000..60ee0f9 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_handles_send.c @@ -0,0 +1,147 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_handles_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the object handle array to the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* storage_id StorageID */ +/* object_format_code Format code filter */ +/* object_association Object Handle Association */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_utility_memory_set Set memory */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_handles_send(UX_SLAVE_CLASS_PIMA *pima, + ULONG storage_id, + ULONG object_format_code, + ULONG object_association) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG object_handles_array_length; +UCHAR *object_handles_array; + + UX_PARAMETER_NOT_USED(storage_id); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_HANDLES_SEND, pima, storage_id, object_format_code, object_association, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + object_handles_array = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Fill in the data container type. */ + _ux_utility_short_put(object_handles_array + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(object_handles_array + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_HANDLES); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(object_handles_array + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Get the array from the application. */ + status = pima -> ux_device_class_pima_object_handles_get(pima, object_format_code, + object_association, (ULONG *) (object_handles_array + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE), + (UX_DEVICE_CLASS_PIMA_ARRAY_BUFFER_SIZE / sizeof(ULONG)) -1); + + /* Result should always be OK, but to be sure .... */ + if (status != UX_SUCCESS) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_FORMAT_CODE, 0, 0, 0, 0); + + else + { + + /* Compute the overall length of the handle arrays. */ + object_handles_array_length = (_ux_utility_long_get(object_handles_array + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE) +1) * (ULONG)sizeof(ULONG); + + /* Add the header size. */ + object_handles_array_length += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Fill in the size of the response header. */ + _ux_utility_long_put(object_handles_array + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + object_handles_array_length); + + /* Send a data payload with the object handles array. */ + status = _ux_device_stack_transfer_request(transfer_request, object_handles_array_length, 0); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + } + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_info_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_info_get.c new file mode 100644 index 0000000..fe6fe48 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_info_get.c @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_info_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the object info structure to the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_descriptor_pack Pack descriptor */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_info_get(UX_SLAVE_CLASS_PIMA *pima, ULONG object_handle) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_CLASS_PIMA_OBJECT *object; +ULONG object_info_length; +UCHAR *object_info; +UCHAR *object_info_pointer; +ULONG unicode_string_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_INFO_GET, pima, object_handle, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the object info from the application. */ + status = pima -> ux_device_class_pima_object_info_get(pima, object_handle, &object); + + /* Check for error. */ + if (status != UX_SUCCESS) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_HANDLE, 0, 0, 0, 0); + + else + { + + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + object_info = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Fill in the data container type. */ + _ux_utility_short_put(object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_INFO); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Allocate the device info pointer to the beginning of the dynamic object info field. */ + object_info_pointer = object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* The object info structure coming from the application needs to be packed. */ + _ux_utility_descriptor_pack((UCHAR *) object, + _ux_system_class_pima_object_structure, + UX_DEVICE_CLASS_PIMA_OBJECT_ENTRIES, + object_info_pointer); + + /* Copy the object filename field. Point to the beginning of the object description string. */ + object_info_pointer += UX_DEVICE_CLASS_PIMA_OBJECT_VARIABLE_OFFSET; + + /* Get the unicode string length for the filename. */ + unicode_string_length = ((ULONG) *object -> ux_device_class_pima_object_filename * 2 ) + 1; + + /* Copy that string into the object description field. */ + _ux_utility_memory_copy(object_info_pointer, object -> ux_device_class_pima_object_filename, unicode_string_length); + + /* Point to the next field. */ + object_info_pointer += unicode_string_length; + + /* Get the unicode string length of the capture date. */ + unicode_string_length = ((ULONG) *object -> ux_device_class_pima_object_capture_date *2 ) + 1; + + /* Copy that string into the capture date field. */ + _ux_utility_memory_copy(object_info_pointer, object -> ux_device_class_pima_object_capture_date, unicode_string_length); + + /* Point to the next field. */ + object_info_pointer += unicode_string_length; + + + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object -> ux_device_class_pima_object_modification_date * 2 ) + 1; + + /* Copy that string into the modification date field. */ + _ux_utility_memory_copy(object_info_pointer, object -> ux_device_class_pima_object_modification_date, unicode_string_length); + + /* Point to the next field. */ + object_info_pointer += unicode_string_length; + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object -> ux_device_class_pima_object_keywords * 2 ) +1; + + /* Copy that string into the keywords field. */ + _ux_utility_memory_copy(object_info_pointer, object -> ux_device_class_pima_object_keywords, unicode_string_length); + + /* Point to the end of the variable length. */ + object_info_pointer += unicode_string_length; + + /* Compute the overall length of the device info structure. */ + object_info_length = (ULONG) ((ALIGN_TYPE) object_info_pointer - (ALIGN_TYPE) object_info); + + /* Fill in the size of the response header. */ + _ux_utility_long_put(object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + object_info_length); + + /* Send a data payload with the object info data set. */ + status = _ux_device_stack_transfer_request(transfer_request, object_info_length, 0); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + } + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_info_send.c b/common/usbx_device_classes/src/ux_device_class_pima_object_info_send.c new file mode 100644 index 0000000..1ff436d --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_info_send.c @@ -0,0 +1,244 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_info_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives an object info structure from the host */ +/* before receiving the actual data. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_info_send(UX_SLAVE_CLASS_PIMA *pima, ULONG storage_id, ULONG parent_object_handle) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_CLASS_PIMA_OBJECT *object; +UCHAR *object_info; +UCHAR *object_info_pointer; +ULONG unicode_string_length; +ULONG object_handle; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECT_INFO_SEND, pima, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_out_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + object_info = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Get the data payload. */ + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE, + UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE); + + /* Check if there was an error. If so, stall the endpoint. */ + if (status != UX_SUCCESS) + { + + /* Stall the endpoint. */ + _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_out_endpoint); + + /* Return the status. */ + return(status); + + } + + /* Allocate some memory for the object. */ + object = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_PIMA_OBJECT)); + + /* Check for successful allocation. */ + if (object == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Allocate the device info pointer to the beginning of the dynamic object info field. */ + object_info_pointer = object_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Uncompress the object descriptor, at least the fixed part. */ + _ux_utility_descriptor_parse(object_info_pointer, + _ux_system_class_pima_object_structure, + UX_DEVICE_CLASS_PIMA_OBJECT_ENTRIES, + (UCHAR *) object); + + /* Copy the object filename field. Point to the beginning of the object description string. */ + object_info_pointer = object_info_pointer + UX_DEVICE_CLASS_PIMA_OBJECT_VARIABLE_OFFSET; + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object_info_pointer * 2) + 1; + + /* Ensure there's enough space for this string. */ + if (unicode_string_length > UX_DEVICE_CLASS_PIMA_UNICODE_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the object description field. */ + _ux_utility_memory_copy(object -> ux_device_class_pima_object_filename, object_info_pointer, unicode_string_length); + + /* Point to the next field. */ + object_info_pointer += unicode_string_length; + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object_info_pointer * 2) + 1; + + /* Ensure there's enough space for this string. */ + if (unicode_string_length > UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the capture date field. */ + _ux_utility_memory_copy(object -> ux_device_class_pima_object_capture_date, object_info_pointer, unicode_string_length); + + /* Point to the next field. */ + object_info_pointer += unicode_string_length; + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object_info_pointer * 2) + 1; + + /* Ensure there's enough space for this string. */ + if (unicode_string_length > UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the modification date field. */ + _ux_utility_memory_copy(object -> ux_device_class_pima_object_modification_date, object_info_pointer, unicode_string_length); + + /* Point to the next field. */ + object_info_pointer += unicode_string_length; + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object_info_pointer * 2) + 1; + + /* Ensure there's enough space for this string. */ + if (unicode_string_length > UX_DEVICE_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the keywords field. */ + _ux_utility_memory_copy(object -> ux_device_class_pima_object_keywords, object_info_pointer, unicode_string_length); + + /* Reset the rest of the other parameters. */ + object -> ux_device_class_pima_object_state = 0; + object -> ux_device_class_pima_object_offset = 0; + object -> ux_device_class_pima_object_transfer_status = 0; + object -> ux_device_class_pima_object_handle_id = 0; + object -> ux_device_class_pima_object_length = 0; + + /* Send the object to the application. */ + status = pima -> ux_device_class_pima_object_info_send(pima, object, storage_id, parent_object_handle, &object_handle); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 3, pima -> ux_device_class_pima_storage_id, + parent_object_handle, object_handle); + + /* Store the object handle. It will be used for the OBJECT_SEND command. */ + pima -> ux_device_class_pima_current_object_handle = object_handle; + } + else + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR, 0, 0, 0, 0); + } + + /* Free the resources. */ + _ux_utility_memory_free(object); + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_prop_desc_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_prop_desc_get.c new file mode 100644 index 0000000..374b1ce --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_prop_desc_get.c @@ -0,0 +1,169 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_prop_desc_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Return an Object Property Description dataset for a format code and */ +/* a specific object property. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* object_property Object Property */ +/* object_format_code Object format for which the */ +/* properties supported are. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_prop_desc_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_property, + ULONG object_format_code) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *object_prop_dataset; +ULONG object_prop_dataset_length; +UCHAR *object_props_desc; +UCHAR *object_props_desc_end; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_GET_OBJECT_PROP_DESC, pima, object_property, object_format_code, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + object_props_desc = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Save the end of the object info. */ + object_props_desc_end = object_props_desc + UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + /* Fill in the data container type. */ + _ux_utility_short_put(object_props_desc + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(object_props_desc + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROP_DESC); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(object_props_desc + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Call the application to retrieve the property description dataset. */ + status = pima -> ux_device_class_pima_object_prop_desc_get(pima, object_property, object_format_code, &object_prop_dataset, &object_prop_dataset_length); + + /* See if we have the right format code and object property. */ + if (status == UX_SUCCESS) + { + + /* We have found the object property for the format code requested, retrieve the dataset. */ + + /* Do we have enough space? */ + if (object_props_desc + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + object_prop_dataset_length <= object_props_desc_end) + { + + /* Copy the object property array. */ + _ux_utility_memory_copy(object_props_desc + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, + object_prop_dataset, object_prop_dataset_length); + + /* Add the header size. */ + object_prop_dataset_length += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Fill in the size of the response header. */ + _ux_utility_long_put(object_props_desc + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + object_prop_dataset_length); + + /* Send a data payload with the object props array. */ + status = _ux_device_stack_transfer_request(transfer_request, object_prop_dataset_length, 0); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + /* Return status. */ + return(status); + } + else + { + + /* The dataset is too large for our buffer. */ + + /* Report the error to the application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + + /* Report the error. */ + status = UX_MEMORY_INSUFFICIENT; + } + } + + /* We get here when we did not find the object format code or the dataset was too large. */ + + /* Now we return a response with error code. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OBJECT_PROP_NOT_SUPPORTED, 0, 0, 0, 0); + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_prop_value_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_prop_value_get.c new file mode 100644 index 0000000..0683fab --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_prop_value_get.c @@ -0,0 +1,169 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_prop_value_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Return an Object Property Value. The value is fetched by calling the */ +/* application which initialized a call back pointer. The application */ +/* will copy the value at the specified address. The length of the */ +/* value of the object will be returned to compute the length of the */ +/* payload packet. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* object_handle Object Handle */ +/* object_property_code Object Property code for */ +/* which the value is obtained. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_prop_value_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle, + ULONG object_property_code) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *pima_data_buffer; +UCHAR *pima_data_buffer_end; +UCHAR *object_property_value; +ULONG object_property_value_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_GET_OBJECT_PROP_VALUE, pima, object_handle, object_property_code, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + pima_data_buffer = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Save the end of the buffer. */ + pima_data_buffer_end = pima_data_buffer + UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + /* Fill in the data container type. */ + _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROP_VALUE); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Ask the application to retrieve for us the object prop value. */ + status = pima -> ux_device_class_pima_object_prop_value_get(pima, object_handle, object_property_code, &object_property_value, &object_property_value_length); + + /* Result should always be OK, but to be sure .... */ + if (status != UX_SUCCESS) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); + + else + { + + /* Check if the prop value will fit. */ + if (pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + object_property_value_length <= pima_data_buffer_end) + { + + /* Copy the property dataset into the local buffer. */ + _ux_utility_memory_copy(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, object_property_value, object_property_value_length); + + /* Add the header size to the payload. */ + object_property_value_length += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Fill in the size of the response header. */ + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + object_property_value_length); + + /* Send a data payload with the object props array. */ + status = _ux_device_stack_transfer_request(transfer_request, object_property_value_length, 0); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + } + else + { + + /* The prop value doesn't fit. */ + + /* Report the error to the application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + + /* Return response code to host. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR, 0, 0, 0, 0); + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + } + } + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_prop_value_set.c b/common/usbx_device_classes/src/ux_device_class_pima_object_prop_value_set.c new file mode 100644 index 0000000..0ac6a35 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_prop_value_set.c @@ -0,0 +1,152 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_prop_value_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Return an Object Property Value. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* object_handle Object Handle */ +/* object_property_code Object Property code for */ +/* which the value is obtained. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_prop_value_set(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle, + ULONG object_property_code) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *pima_data_buffer; +UCHAR *object_property_value; +ULONG object_property_value_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_SET_OBJECT_PROP_VALUE, pima, object_handle, object_property_code, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_out_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + pima_data_buffer = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Get the data payload. */ + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_PIMA_OBJECT_PROP_VALUE_BUFFER_SIZE, + UX_DEVICE_CLASS_PIMA_OBJECT_PROP_VALUE_BUFFER_SIZE); + + /* Check if there was an error. If so, stall the endpoint. */ + if (status != UX_SUCCESS) + { + + /* Stall the endpoint. */ + _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_out_endpoint); + + /* Return the status. */ + return(status); + + } + + /* Allocate the device info pointer to the beginning of the dynamic object info field. */ + object_property_value = pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Obtain the length of the data payload. */ + object_property_value_length = transfer_request -> ux_slave_transfer_request_actual_length; + + /* Ensure there is some data payload. */ + if (object_property_value_length > UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE) + { + + /* Take out the header. */ + object_property_value_length -= UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Send the object to the application. */ + status = pima -> ux_device_class_pima_object_prop_value_set(pima, object_handle, object_property_code, object_property_value, object_property_value_length); + + /* Check error code from application. */ + if (status == UX_SUCCESS) + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + else + + /* We return an error. The code is passed by the application. */ + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); + + } + else + { + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); + + /* Status error. */ + status = UX_ERROR; + + } + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_props_supported_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_props_supported_get.c new file mode 100644 index 0000000..3b4289b --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_props_supported_get.c @@ -0,0 +1,190 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_prop_supported_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Return an Object Property Code array of supported object properties */ +/* in the first parameter. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* object_format_code Object format for which the */ +/* properties supported are. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_props_supported_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_format_code) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG object_props_list_items; +ULONG object_props_list_length; +UCHAR *object_props_list; +USHORT *object_props_list_pointer; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECTS_PROPS_SUPPORTED_GET, pima, object_format_code, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + object_props_list = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Fill in the data container type. */ + _ux_utility_short_put(object_props_list + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(object_props_list + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROPS_SUPPORTED); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(object_props_list + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Get the pointer to the list of arrays. */ + object_props_list_pointer = pima -> ux_device_class_pima_object_properties_list; + + /* Find the object format within the object props arrays. */ + while (*object_props_list_pointer != 0) + { + /* See what the format code is. */ + if (*object_props_list_pointer == (USHORT) object_format_code) + { + + /* We have found the format code requested, retrieve the array of props. */ + /* Retrieve the number of properties for this format code. */ + object_props_list_items = (ULONG) *(object_props_list_pointer + 1); + + /* Compute the overall length of the object properties array = number of properties + size of array in USHORT. */ + object_props_list_length = (object_props_list_items * (ULONG)sizeof(USHORT)) + (ULONG)sizeof(ULONG); + + /* Add the header size. */ + object_props_list_length += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Fill in the size of the response header. */ + _ux_utility_long_put(object_props_list + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + object_props_list_length); + + /* Update the destination pointer. */ + object_props_list += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Insert the number of elements in the array. */ + _ux_utility_long_put(object_props_list, object_props_list_items); + + /* Add the length of the array. */ + object_props_list += sizeof(ULONG); + + /* Point the object_props_list_pointer to the props supported. Skip the object format and the number + of properties. */ + object_props_list_pointer += 2; + + /* Create the array in little endian format for transfer to host. */ + while(object_props_list_items--) + { + + /* Insert the object property in little endian. */ + _ux_utility_short_put(object_props_list, *object_props_list_pointer); + + /* Update target pointer. */ + object_props_list += sizeof(SHORT); + + /* Update source pointer. */ + object_props_list_pointer++; + + } + + /* Send a data payload with the object props array. */ + status = _ux_device_stack_transfer_request(transfer_request, object_props_list_length, 0); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + /* Return status. */ + return(status); + } + else + { + + /* We need to skip this object format and point to the next. */ + /* Retrieve the number of properties for this format code. */ + object_props_list_items = *(object_props_list_pointer + 1); + + /* Add the number of items to skip to the current list pointer. */ + object_props_list_pointer += object_props_list_items + 2; + + } + } + + /* We get here when we did not find the object format code. */ + status = _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_OBJECT_FORMAT_CODE, 0, 0, 0, 0); + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_references_get.c b/common/usbx_device_classes/src/ux_device_class_pima_object_references_get.c new file mode 100644 index 0000000..dfe537d --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_references_get.c @@ -0,0 +1,163 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_references_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Return object references associated with an object handle. */ +/* The pima class will call the application to get the array of */ +/* references. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* object_handle Object Handle for which */ +/* references are obtained. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_references_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *pima_data_buffer; +UCHAR *pima_data_buffer_end; +UCHAR *object_references; +ULONG object_references_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_GET_OBJECT_REFERENCES, pima, object_handle, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + pima_data_buffer = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Save end of buffer. */ + pima_data_buffer_end = pima_data_buffer + UX_SLAVE_REQUEST_DATA_MAX_LENGTH; + + /* Fill in the data container type. */ + _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_REFERENCES); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Ask the application to retrieve for us the object references. */ + status = pima -> ux_device_class_pima_object_references_get(pima, object_handle, &object_references, &object_references_length); + + /* Result should always be OK, but to be sure .... */ + if (status != UX_SUCCESS) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); + + else + { + + /* Check if there enough space in our buffer. */ + if (pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + object_references_length <= pima_data_buffer_end) + { + + /* Copy the property dataset into the local buffer. */ + _ux_utility_memory_copy(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, object_references, object_references_length); + + /* Add the header size to the payload. */ + object_references_length += UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Fill in the size of the response header. */ + _ux_utility_long_put(pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + object_references_length); + + /* Send a data payload with the object references array. */ + status = _ux_device_stack_transfer_request(transfer_request, object_references_length, 0); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + } + else + { + + /* Report the error to the application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + + /* We return an error code to the host. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_GENERAL_ERROR, 0, 0, 0, 0); + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + } + } + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_object_references_set.c b/common/usbx_device_classes/src/ux_device_class_pima_object_references_set.c new file mode 100644 index 0000000..e569dc8 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_object_references_set.c @@ -0,0 +1,145 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_references_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Set object references associated with an object handle. */ +/* The pima class will call the application to set the array of */ +/* references. */ +/* */ +/* */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* object_handle Object Handle */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_object_references_set(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *pima_data_buffer; +UCHAR *object_references; +ULONG object_references_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_SET_OBJECT_REFERENCES, pima, object_handle, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_out_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + pima_data_buffer = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Get the data payload. */ + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_PIMA_OBJECT_PROP_VALUE_BUFFER_SIZE, + UX_DEVICE_CLASS_PIMA_OBJECT_PROP_VALUE_BUFFER_SIZE); + + /* Check if there was an error. If so, stall the endpoint. */ + if (status != UX_SUCCESS) + { + + /* Stall the endpoint. */ + _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_out_endpoint); + + /* Return the status. */ + return(status); + + } + + /* Allocate the device info pointer to the beginning of the dynamic object info field. */ + object_references = pima_data_buffer + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Obtain the length of the data payload. */ + object_references_length = transfer_request -> ux_slave_transfer_request_actual_length; + + /* Ensure there is some data payload. */ + if (object_references_length > UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE) + { + + /* Take out the header. */ + object_references_length -= UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Send the object references to the application. */ + status = pima -> ux_device_class_pima_object_references_set(pima, object_handle, object_references, object_references_length); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + } + else + { + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); + + /* Status error. */ + status = UX_ERROR; + + } + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_objects_number_send.c b/common/usbx_device_classes/src/ux_device_class_pima_objects_number_send.c new file mode 100644 index 0000000..16a4d1e --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_objects_number_send.c @@ -0,0 +1,102 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_object_number_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the number of objects in the system. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_objects_number_send(UX_SLAVE_CLASS_PIMA *pima, + ULONG storage_id, + ULONG object_format_code, + ULONG object_association) +{ + +UINT status; +ULONG object_number; + + UX_PARAMETER_NOT_USED(storage_id); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_OBJECTS_NUMBER_SEND, pima, storage_id, object_format_code, object_association, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the number of objects from the application. */ + status = pima -> ux_device_class_pima_object_number_get(pima, object_format_code, object_association, &object_number); + + /* Result should always be OK, but to be sure .... */ + if (status != UX_SUCCESS) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_INVALID_PARAMETER, 0, 0, 0, 0); + + else + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 1, object_number, 0, 0); + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_partial_object_data_get.c b/common/usbx_device_classes/src/ux_device_class_pima_partial_object_data_get.c new file mode 100644 index 0000000..84a22f5 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_partial_object_data_get.c @@ -0,0 +1,307 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_partial_object_data_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the partial object data to the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_partial_object_data_get(UX_SLAVE_CLASS_PIMA *pima, + ULONG object_handle, + ULONG offset_requested, + ULONG length_requested) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_CLASS_PIMA_OBJECT *object; +UCHAR *object_data; +ULONG object_offset; +ULONG object_length; +ULONG total_length; +ULONG object_length_demanded; +ULONG object_length_received; +ULONG object_length_transfer; +ULONG object_bytes_sent; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_PARTIAL_OBJECT_DATA_GET, pima, object_handle, offset_requested, length_requested, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the object info from the application. */ + status = pima -> ux_device_class_pima_object_info_get(pima, object_handle, &object); + + /* Check for error. */ + if (status == UX_SUCCESS) + { + + /* Get the object length. */ + object_length = object -> ux_device_class_pima_object_length; + + /* Check how much to return. */ + if ((object_length - offset_requested) > length_requested) + { + + /* Return the maximum demanded. */ + total_length = length_requested + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Set the number of bytes we will send back. */ + object_bytes_sent = length_requested; + } + + else + { + + /* Return the maximum we can. */ + total_length = (object_length - offset_requested) + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Set the number of bytes we will send back. */ + object_bytes_sent = object_length - offset_requested; + + } + + /* Reset the offset. */ + object_offset = 0; + + /* Obtain the pointer to the transfer request of the bulk in endpoint. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + object_data = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Fill in the total length to be sent (header + payload. */ + _ux_utility_long_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + total_length); + + /* Fill in the data container type. */ + _ux_utility_short_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_PARTIAL_OBJECT); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Assuming the host will ask for the entire object. */ + while (total_length != 0) + { + + /* If this is the first packet, we have to take into account the + header. */ + if (object_offset == 0) + { + + /* Calculate the maximum length for the first packet. */ + object_length_demanded = UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE - + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Can we get that much from the application ? */ + if (object_length_demanded > object_bytes_sent) + + /* We ask too much. */ + object_length_demanded = object_bytes_sent; + + /* Obtain some data from the application. */ + status = pima -> ux_device_class_pima_object_data_get(pima, object_handle, object_data + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, + object_offset + offset_requested, + object_length_demanded, + &object_length_received); + + /* Check status, if we have a problem, we abort. */ + if (status != UX_SUCCESS) + { + + /* We need to inform the host of an error. */ + status = UX_ERROR; + break; + } + else + { + /* Adjust the length of the object. */ + object_length -= object_length_received; + + /* Adjust the length to be sent. */ + object_length_transfer = object_length_received + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE; + + } + + } + else + { + + /* Calculate the maximum length for the first packet. */ + object_length_demanded = UX_DEVICE_CLASS_PIMA_OBJECT_INFO_BUFFER_SIZE; + + /* Can we get that much from the application ? */ + if (object_length_demanded > total_length) + + /* We ask too much. */ + object_length_demanded = total_length; + + /* Obtain some data from the application. */ + status = pima -> ux_device_class_pima_object_data_get(pima, object_handle, object_data, object_offset + offset_requested, + object_length_demanded, + &object_length_received); + + /* Check status, if we have a problem, we abort. */ + if (status != UX_SUCCESS) + { + + /* We need to inform the host of an error. */ + status = UX_ERROR; + break; + + } + + else + { + /* Adjust the length of the object. */ + object_length -= object_length_received; + + /* Adjust the length to be sent. */ + object_length_transfer = object_length_received; + } + + } + + /* Check if it is the last transfer. */ + if (object_length_transfer != total_length) + + /* Not the last transfer, just send the object data to the host. */ + status = _ux_device_stack_transfer_request(transfer_request, object_length_transfer, object_length_transfer); + + else + + /* It's the last transfer, we need to send a ZLP if the last packet is a full packet. */ + status = _ux_device_stack_transfer_request(transfer_request, object_length_transfer, 0); + + /* Check for the status. We may have had a request to cancel the transaction from the host. */ + if (status != UX_SUCCESS) + { + + /* Check the completion code for transfer abort from the host. */ + if (transfer_request -> ux_slave_transfer_request_status == UX_TRANSFER_STATUS_ABORT) + { + + /* Do not proceed. */ + return(UX_ERROR); + + } + + else + + { + + /* We need to inform the host of an error. */ + status = UX_ERROR; + break; + + } + } + + else + + { + + /* Do some sanity check. */ + if (total_length < object_length_received) + { + /* We have an overflow. Do not proceed. */ + status = UX_ERROR; + break; + + } + + /* Adjust the offset within the object data. */ + object_offset += object_length_received; + + /* Update the total length to be sent. */ + total_length -= object_length_transfer; + + } + + } + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 1, object_bytes_sent, 0, 0); + + } + + /* Check if status is OK. */ + if (status != UX_SUCCESS) + + /* We need to stall the bulk in pipe. This is the method used by Pima devices to + cancel a transaction. */ + _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_in_endpoint); + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_response_send.c b/common/usbx_device_classes/src/ux_device_class_pima_response_send.c new file mode 100644 index 0000000..02ec295 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_response_send.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_response_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns a response to a pima command to the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* response_code Response code */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_response_send(UX_SLAVE_CLASS_PIMA *pima, ULONG response_code, + ULONG number_parameters, + ULONG pima_parameter_1, + ULONG pima_parameter_2, + ULONG pima_parameter_3) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *response; +ULONG header_size; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_RESPONSE_SEND, pima, response_code, number_parameters, pima_parameter_1, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Calculate the header size. */ + header_size = UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + (ULONG)(sizeof(ULONG) * number_parameters); + + /* Obtain memory for this response. Use the transfer request pre-allocated memory. */ + response = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Fill in the size of the response header. */ + _ux_utility_long_put(response + UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_LENGTH, header_size); + + /* Fill in the response container type. */ + _ux_utility_short_put(response + UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_RESPONSE_BLOCK); + + /* Fill in the response code. */ + _ux_utility_short_put(response + UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_CODE, + (USHORT)response_code); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(response + UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Parse each parameter and insert it if needed. */ + switch (number_parameters) + { + + case 3 : + _ux_utility_long_put(response + UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_PARAMETERS + (sizeof(ULONG) * 2), + pima_parameter_3); + /* Intentionally fallthrough to "case 2" */ + /* fall through */ + case 2 : + _ux_utility_long_put(response + UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_PARAMETERS + (sizeof(ULONG) * 1), + pima_parameter_2); + /* Intentionally fallthrough to "case 1" */ + /* fall through */ + case 1 : + _ux_utility_long_put(response + UX_DEVICE_CLASS_PIMA_RESPONSE_HEADER_PARAMETERS , + pima_parameter_1); + /* Intentionally fallthrough to "default" */ + /* fall through */ + default : + break; + + } + + /* Send the response block. */ + status = _ux_device_stack_transfer_request(transfer_request, header_size, 0); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_storage_format.c b/common/usbx_device_classes/src/ux_device_class_pima_storage_format.c new file mode 100644 index 0000000..f9d04a0 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_storage_format.c @@ -0,0 +1,98 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_storage_format PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function informs the application that the storage media */ +/* should be reformatted. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* storage_id Storage ID */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_storage_format(UX_SLAVE_CLASS_PIMA *pima, ULONG storage_id) +{ + +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_STORAGE_FORMAT, pima, storage_id, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Invoke the application callback function. */ + status = pima -> ux_device_class_pima_storage_format(pima, storage_id); + + /* Check for error. */ + if (status != UX_SUCCESS) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); + + else + + /* We return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_storage_id_send.c b/common/usbx_device_classes/src/ux_device_class_pima_storage_id_send.c new file mode 100644 index 0000000..8ab1ab6 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_storage_id_send.c @@ -0,0 +1,125 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_storage_id_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the storage id array to the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Pima Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_storage_id_send(UX_SLAVE_CLASS_PIMA *pima) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG storage_id_length; +UCHAR *storage_id; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_STORAGE_ID_SEND, pima, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object. Use the transfer request pre-allocated memory. */ + storage_id = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Fill in the data container type. */ + _ux_utility_short_put(storage_id + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(storage_id + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_STORAGE_IDS); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(storage_id + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* We have one element only to report. */ + _ux_utility_long_put(storage_id + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE, UX_DEVICE_CLASS_PIMA_MAX_STORAGE_IDS); + + /* Insert the element ID. */ + _ux_utility_long_put(storage_id + UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + sizeof(ULONG), pima -> ux_device_class_pima_storage_id); + + /* Compute the overall length of the device info structure. */ + storage_id_length = UX_DEVICE_CLASS_PIMA_DATA_HEADER_SIZE + sizeof(ULONG) + (sizeof(ULONG) * UX_DEVICE_CLASS_PIMA_MAX_STORAGE_IDS); + + /* Fill in the size of the response header. */ + _ux_utility_long_put(storage_id + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + storage_id_length); + + /* Send a data payload with the storage id data set. */ + status = _ux_device_stack_transfer_request(transfer_request, storage_id_length, 0); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_storage_info_get.c b/common/usbx_device_classes/src/ux_device_class_pima_storage_info_get.c new file mode 100644 index 0000000..47581d9 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_storage_info_get.c @@ -0,0 +1,181 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_storage_info_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the storage info structure to the host. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 32-bit value */ +/* _ux_utility_string_to_unicode Ascii string to unicode */ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_pima_storage_info_get(UX_SLAVE_CLASS_PIMA *pima, ULONG storage_id) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG storage_info_length; +UCHAR *storage_info; +UCHAR *storage_info_pointer; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_PIMA_STORAGE_INFO_SEND, pima, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &pima -> ux_device_class_pima_bulk_in_endpoint -> ux_slave_endpoint_transfer_request; + + /* Obtain memory for this object info. Use the transfer request pre-allocated memory. */ + storage_info = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Update the storage information. We get the volatile parameters from the application. */ + status = pima -> ux_device_class_pima_storage_info_get(pima, storage_id); + + /* Check for error. */ + if (status != UX_SUCCESS) + + /* We return an error. */ + _ux_device_class_pima_response_send(pima, status, 0, 0, 0, 0); + + else + { + + /* Fill in the data container type. */ + _ux_utility_short_put(storage_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TYPE, + UX_DEVICE_CLASS_PIMA_CT_DATA_BLOCK); + + /* Fill in the data code. */ + _ux_utility_short_put(storage_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_CODE, + UX_DEVICE_CLASS_PIMA_OC_GET_STORAGE_INFO); + + /* Fill in the Transaction ID. */ + _ux_utility_long_put(storage_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_device_class_pima_transaction_id); + + /* Allocate the device info pointer to the beginning of the dynamic storage info field. */ + storage_info_pointer = storage_info + UX_DEVICE_CLASS_PIMA_STORAGE_FREE_STORAGE_DESCRIPTION; + + /* Fill in the storage type. */ + _ux_utility_short_put(storage_info + UX_DEVICE_CLASS_PIMA_STORAGE_TYPE, + (USHORT)pima -> ux_device_class_pima_storage_type); + + /* Fill in the file system type. */ + _ux_utility_short_put(storage_info + UX_DEVICE_CLASS_PIMA_STORAGE_FILE_SYSTEM_TYPE, + (USHORT)pima -> ux_device_class_pima_storage_file_system_type); + + /* Fill in the access capability. */ + _ux_utility_short_put(storage_info + UX_DEVICE_CLASS_PIMA_STORAGE_ACCESS_CAPABILITY, + (USHORT)pima -> ux_device_class_pima_storage_access_capability); + + /* Fill in the low dword of max capacity. */ + _ux_utility_long_put(storage_info + UX_DEVICE_CLASS_PIMA_STORAGE_MAX_CAPACITY_LOW, + pima -> ux_device_class_pima_storage_max_capacity_low); + + /* Fill in the high dword of max capacity. */ + _ux_utility_long_put(storage_info + UX_DEVICE_CLASS_PIMA_STORAGE_MAX_CAPACITY_HIGH, + pima -> ux_device_class_pima_storage_max_capacity_high); + + /* Fill in the low dword of free space. */ + _ux_utility_long_put(storage_info + UX_DEVICE_CLASS_PIMA_STORAGE_FREE_SPACE_LOW, + pima -> ux_device_class_pima_storage_free_space_low); + + /* Fill in the high dword of free space. */ + _ux_utility_long_put(storage_info + UX_DEVICE_CLASS_PIMA_STORAGE_FREE_SPACE_HIGH, + pima -> ux_device_class_pima_storage_free_space_high); + + /* Fill in the free space in image. */ + _ux_utility_long_put(storage_info + UX_DEVICE_CLASS_PIMA_STORAGE_FREE_SPACE_IMAGE, + pima -> ux_device_class_pima_storage_free_space_image); + + /* Fill in the storage description string. */ + _ux_utility_string_to_unicode(pima -> ux_device_class_pima_storage_description, storage_info_pointer); + + /* Update the storage info pointer. */ + storage_info_pointer += (ULONG) (*storage_info_pointer * 2) + 1; + + /* Fill in the volume label string. */ + _ux_utility_string_to_unicode(pima -> ux_device_class_pima_storage_volume_label, storage_info_pointer); + + /* Update the storage info pointer. */ + storage_info_pointer += (ULONG) (*storage_info_pointer* 2) + 1; + + /* Compute the overall length of the storage info structure. */ + storage_info_length = (ULONG) ((ALIGN_TYPE) storage_info_pointer - (ALIGN_TYPE) storage_info); + + /* Fill in the size of the response header. */ + _ux_utility_long_put(storage_info + UX_DEVICE_CLASS_PIMA_DATA_HEADER_LENGTH, + storage_info_length); + + /* Send a data payload with the storage info data set. */ + status = _ux_device_stack_transfer_request(transfer_request, storage_info_length, 0); + + /* Now we return a response with success. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + } + + /* Return completion status. */ + return(status); +} + + diff --git a/common/usbx_device_classes/src/ux_device_class_pima_thread.c b/common/usbx_device_classes/src/ux_device_class_pima_thread.c new file mode 100644 index 0000000..d1a4a19 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_pima_thread.c @@ -0,0 +1,465 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_pima.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_pima_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the pima class. */ +/* */ +/* INPUT */ +/* */ +/* pima_class Address of pima class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_utility_thread_create Create thread */ +/* _ux_utility_thread_suspend Suspend thread */ +/* _ux_utility_short_get Get 16-bit value */ +/* _ux_utility_long_get Get 32-bit value */ +/* _ux_device_class_pima_device_info_send */ +/* Send PIMA device info */ +/* _ux_device_class_pima_storage_id_send Send PIMA storage ID */ +/* _ux_device_class_pima_storage_info_get */ +/* Get PIMA storage info get */ +/* _ux_device_class_pima_objects_number_send */ +/* Send number of PIMA objects */ +/* _ux_device_class_pima_object_handles_send */ +/* Send PIMA object handlers */ +/* _ux_device_class_pima_object_info_get Get PIMA object info */ +/* _ux_device_class_pima_object_data_get Get PIMA object data */ +/* _ux_device_class_pima_object_delete Delete PIMA object */ +/* _ux_device_class_pima_object_info_send */ +/* Send PIMA object info */ +/* _ux_device_class_pima_object_data_send */ +/* Send PIMA object data */ +/* _ux_device_class_pima_storage_format Format storage */ +/* _ux_device_class_pima_device_reset Reset device */ +/* _ux_device_class_pima_object_props_supported_get */ +/* Get support PIMA object */ +/* properties */ +/* _ux_device_class_pima_object_prop_desc_get */ +/* Get PIMA object property */ +/* descriptor */ +/* _ux_device_class_pima_object_prop_value_get */ +/* Get PIMA object property value*/ +/* _ux_device_class_pima_object_prop_value_set */ +/* Set PIMA object property value*/ +/* _ux_device_class_pima_object_references_get */ +/* Get PIMA object references */ +/* _ux_device_class_pima_device_prop_desc_get */ +/* Get PIMA device property */ +/* descriptor */ +/* _ux_device_class_pima_device_prop_value_get */ +/* Get PIMA device property value*/ +/* _ux_device_class_pima_device_prop_value_set */ +/* Set PIMA device property value*/ +/* _ux_device_class_pima_response_send Send PIMA response */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_pima_thread(ULONG pima_class) +{ + +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_PIMA *pima; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *pima_command; +ULONG pima_command_code; +ULONG pima_parameter_1; +ULONG pima_parameter_2; +ULONG pima_parameter_3; +UINT status; + + + /* Cast properly the pima instance. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_SLAVE_CLASS, pima_class) + + /* Get the pima instance from this class container. */ + pima = (UX_SLAVE_CLASS_PIMA *) class -> ux_slave_class_instance; + + /* Allocate some memory for the thread stack. */ + pima -> ux_device_class_pima_interrupt_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (pima -> ux_device_class_pima_interrupt_thread_stack == UX_NULL) + { + + /* Do not proceed. */ + return; + } + + /* Allocate a semaphore to this thread. */ + status = _ux_utility_semaphore_create(&pima -> ux_device_class_pima_interrupt_thread_semaphore, + "ux_device_class_interrupt_thread_semaphore", 0); + + /* Check completion status. */ + if (status != UX_SUCCESS) + { + + /* Do not proceed. */ + return; + } + + /* The Pima device class needs 2 threads, one is activated by default for the command\response and one needs to be + created here for the interrupt pipe event. */ + status = _ux_utility_thread_create(&pima -> ux_device_class_pima_interrupt_thread, "ux_slave_class_thread_pima_interrupt", + _ux_device_class_pima_interrupt_thread, + (ULONG) (ALIGN_TYPE) pima, (VOID *) pima -> ux_device_class_pima_interrupt_thread_stack, + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check the creation of this thread. */ + if (status != UX_SUCCESS) + { + + /* Do not proceed. */ + return; + } + + UX_THREAD_EXTENSION_PTR_SET(&(pima -> ux_device_class_pima_interrupt_thread), pima) + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* All PIMA commands are on the endpoint OUT, from the host. */ + transfer_request = &pima -> ux_device_class_pima_bulk_out_endpoint -> ux_slave_endpoint_transfer_request; + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, 64, 64); + + /* Check the status */ + if (status == UX_SUCCESS) + { + + /* Obtain the buffer address containing the PIMA command. */ + pima_command = transfer_request -> ux_slave_transfer_request_data_pointer; + + + /* Check to make sure we have a command block. */ + if (_ux_utility_short_get(pima_command + UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_TYPE) == UX_DEVICE_CLASS_PIMA_CT_COMMAND_BLOCK) + { + + /* Save the transaction ID. */ + pima -> ux_device_class_pima_transaction_id = _ux_utility_long_get(pima_command + + UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_TRANSACTION_ID); + + /* Retrieve the command stored in the command block. */ + pima_command_code = _ux_utility_short_get(pima_command + UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_CODE); + + /* Retrieve the parameter 1. */ + pima_parameter_1 = _ux_utility_long_get(pima_command + UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_PARAMETER_1); + + /* Retrieve the parameter 2. */ + pima_parameter_2 = _ux_utility_long_get(pima_command + UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_PARAMETER_2); + + /* Retrieve the parameter 3. */ + pima_parameter_3 = _ux_utility_long_get(pima_command + UX_DEVICE_CLASS_PIMA_COMMAND_HEADER_PARAMETER_3); + + /* We check first if this is a GET_DEVICE_INFO as this is the only command which does not require + a session to be opened. */ + + switch (pima_command_code) + { + + case UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_INFO : + + /* Return the device info to the host. */ + status = _ux_device_class_pima_device_info_send(pima); + break; + + + case UX_DEVICE_CLASS_PIMA_OC_OPEN_SESSION : + + /* Check if session is already opened. */ + if (pima -> ux_device_class_pima_session_id == 0) + { + + /* Session can be opened. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + /* Store the session number. */ + pima -> ux_device_class_pima_session_id = pima_parameter_1; + + break; + + + default : + + + /* Check if a session is opened. */ + if (pima -> ux_device_class_pima_session_id == 0) + { + + /* We cannot proceed since the session is not opened. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_SESSION_NOT_OPEN, 0, 0, 0, 0); + + } + + else + { + + /* Analyze the command stored in the command block. */ + switch (pima_command_code) + { + + case UX_DEVICE_CLASS_PIMA_OC_CLOSE_SESSION : + + /* We close the session. Return OK. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OK, 0, 0, 0, 0); + + /* Session is now closed. */ + pima -> ux_device_class_pima_session_id = 0; + + break; + case UX_DEVICE_CLASS_PIMA_OC_GET_STORAGE_IDS : + + /* Return the array of storage IDs to the host. In this version, we support + only one storage media. */ + status = _ux_device_class_pima_storage_id_send(pima); + break; + + case UX_DEVICE_CLASS_PIMA_OC_GET_STORAGE_INFO : + + /* Return the storage info to the host. */ + status = _ux_device_class_pima_storage_info_get(pima, pima_parameter_1); + break; + + case UX_DEVICE_CLASS_PIMA_OC_GET_NUM_OBJECTS : + + /* Return the number of objects found in the system. */ + status = _ux_device_class_pima_objects_number_send(pima, + pima_parameter_1, pima_parameter_2, pima_parameter_3); + break; + + case UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_HANDLES : + + /* Return the object handles found in the system. */ + status = _ux_device_class_pima_object_handles_send(pima, + pima_parameter_1, pima_parameter_2, pima_parameter_3); + + break; + + case UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_INFO : + + /* Return the object info data set. */ + status = _ux_device_class_pima_object_info_get(pima, pima_parameter_1); + break; + + case UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT : + + /* Return the object data. */ + status = _ux_device_class_pima_object_data_get(pima, pima_parameter_1); + break; + + case UX_DEVICE_CLASS_PIMA_OC_DELETE_OBJECT : + + /* Delete one or more objects. */ + status = _ux_device_class_pima_object_delete(pima, pima_parameter_1); + break; + + case UX_DEVICE_CLASS_PIMA_OC_SEND_OBJECT_INFO : + + /* Accept an object info data set. */ + status = _ux_device_class_pima_object_info_send(pima, pima_parameter_1, pima_parameter_2); + break; + + case UX_DEVICE_CLASS_PIMA_OC_SEND_OBJECT : + /* Accept the object data. */ + status = _ux_device_class_pima_object_data_send(pima); + break; + + case UX_DEVICE_CLASS_PIMA_OC_GET_PARTIAL_OBJECT : + + /* Return the partial object data. */ + status = _ux_device_class_pima_partial_object_data_get(pima, pima_parameter_1, pima_parameter_2, pima_parameter_3); + break; + + case UX_DEVICE_CLASS_PIMA_OC_FORMAT_STORE : + + /* Format the storage device. This calls the application to reset all object handles stored + on the media. */ + status = _ux_device_class_pima_storage_format(pima, pima_parameter_1); + break; + + case UX_DEVICE_CLASS_PIMA_OC_RESET_DEVICE : + + /* Reset the device. This calls the application to reset the device. The session is closed + but all objects retain their properties. */ + status = _ux_device_class_pima_device_reset(pima); + break; + + + case UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROPS_SUPPORTED : + + /* Return an Object Property Code array of supported object properties for the object format that is indicated + in the first parameter. */ + status = _ux_device_class_pima_object_props_supported_get(pima, pima_parameter_1); + break; + + case UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROP_DESC : + + /* Returns the appropriate property that describes the dataset that is indicated in the first parameter. */ + status = _ux_device_class_pima_object_prop_desc_get(pima, pima_parameter_1, pima_parameter_2); + break; + + case UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_PROP_VALUE : + + /* Returns the Object property value. */ + status = _ux_device_class_pima_object_prop_value_get(pima, pima_parameter_1, pima_parameter_2); + break; + + case UX_DEVICE_CLASS_PIMA_OC_SET_OBJECT_PROP_VALUE : + + /* Sets the current value of the object property. */ + status = _ux_device_class_pima_object_prop_value_set(pima, pima_parameter_1, pima_parameter_2); + break; + + case UX_DEVICE_CLASS_PIMA_OC_GET_OBJECT_REFERENCES : + + /* Returns the object handle references. */ + status = _ux_device_class_pima_object_references_get(pima, pima_parameter_1); + break; + + case UX_DEVICE_CLASS_PIMA_OC_SET_OBJECT_REFERENCES : + + /* Set the object handle references. */ + status = _ux_device_class_pima_object_references_set(pima, pima_parameter_1); + break; + + case UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_PROP_DESC : + + /* Returns the appropriate device property. */ + status = _ux_device_class_pima_device_prop_desc_get(pima, pima_parameter_1); + break; + + case UX_DEVICE_CLASS_PIMA_OC_GET_DEVICE_PROP_VALUE : + + /* Returns the device property value. */ + status = _ux_device_class_pima_device_prop_value_get(pima, pima_parameter_1); + break; + + case UX_DEVICE_CLASS_PIMA_OC_SET_DEVICE_PROP_VALUE : + + /* Sets the current value of the device property. */ + status = _ux_device_class_pima_device_prop_value_set(pima, pima_parameter_1); + break; + + case UX_DEVICE_CLASS_PIMA_OC_INITIATE_OPEN_CAPTURE : + case UX_DEVICE_CLASS_PIMA_OC_GET_THUMB : + case UX_DEVICE_CLASS_PIMA_OC_INITIATE_CAPTURE : + case UX_DEVICE_CLASS_PIMA_OC_SELF_TEST : + case UX_DEVICE_CLASS_PIMA_OC_SET_OBJECT_PROTECTION : + case UX_DEVICE_CLASS_PIMA_OC_POWER_DOWN : + case UX_DEVICE_CLASS_PIMA_OC_RESET_DEVICE_PROP_VALUE : + case UX_DEVICE_CLASS_PIMA_OC_TERMINATE_OPEN_CAPTURE : + case UX_DEVICE_CLASS_PIMA_OC_MOVE_OBJECT : + case UX_DEVICE_CLASS_PIMA_OC_COPY_OBJECT : + + /* Functions not yet supported. */ + _ux_device_class_pima_response_send(pima, UX_DEVICE_CLASS_PIMA_RC_OPERATION_NOT_SUPPORTED, 0, 0, 0, 0); + + /* Set error code. */ + status = UX_FUNCTION_NOT_SUPPORTED; + + break; + + default: + + /* The command is unknown, so we stall the endpoint. */ + _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_out_endpoint); + } + + /* Check error code. */ + if (status != UX_SUCCESS) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + + } + } + } + + /* Check error code. */ + if (status != UX_SUCCESS) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + } + else + + /* We have a wrong buffer format. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(pima -> ux_device_class_pima_bulk_out_endpoint); + } + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ + _ux_utility_thread_suspend(&class -> ux_slave_class_thread); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_activate.c b/common/usbx_device_classes/src/ux_device_class_rndis_activate.c new file mode 100644 index 0000000..31c0c17 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_activate.c @@ -0,0 +1,208 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function activates the USB RNDIS device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to rndis command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_network_driver_activate Activate NetX USB interface */ +/* _ux_utility_memory_set Set memory */ +/* _ux_utility_thread_resume Resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_rndis_activate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_RNDIS *rndis; +UX_SLAVE_CLASS *class; +UX_SLAVE_ENDPOINT *endpoint; +ULONG physical_address_msw; +ULONG physical_address_lsw; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + rndis = (UX_SLAVE_CLASS_RNDIS *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Check if this is the Control or Data interface. */ + if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_RNDIS_CLASS_COMMUNICATION_CONTROL) + { + + /* Store the class instance into the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)rndis; + + /* Now the opposite, store the interface in the class instance. */ + rndis -> ux_slave_class_rndis_interface = interface; + + /* If there is a activate function call it. */ + if (rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_instance_activate != UX_NULL) + + /* Invoke the application. */ + rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_instance_activate(rndis); + } + else + + /* This is the DATA Class, only store the rndis instance in the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)rndis; + + /* Locate the endpoints. Interrupt for Control and Bulk in/out for Data. */ + endpoint = interface -> ux_slave_interface_first_endpoint; + + /* Parse all endpoints. */ + while (endpoint != UX_NULL) + { + + /* Check the endpoint direction, and type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) + { + + /* Look at type. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT) + + /* We have found the interrupt endpoint, save it. */ + rndis -> ux_slave_class_rndis_interrupt_endpoint = endpoint; + + else + + /* We have found the bulk in endpoint, save it. */ + rndis -> ux_slave_class_rndis_bulkin_endpoint = endpoint; + + } + else + { + /* Look at type for out endpoint. */ + if ((endpoint -> ux_slave_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT) + + /* We have found the bulk out endpoint, save it. */ + rndis -> ux_slave_class_rndis_bulkout_endpoint = endpoint; + } + + /* Next endpoint. */ + endpoint = endpoint -> ux_slave_endpoint_next_endpoint; + } + + /* Check if this is the Control or Data interface. */ + if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_RNDIS_CLASS_COMMUNICATION_DATA) + { + + /* Now check if all endpoints have been found. */ + if (rndis -> ux_slave_class_rndis_bulkout_endpoint == UX_NULL || rndis -> ux_slave_class_rndis_bulkin_endpoint == UX_NULL || + rndis -> ux_slave_class_rndis_interrupt_endpoint == UX_NULL) + + /* Not all endpoints have been found. Major error, do not proceed. */ + return(UX_ERROR); + + /* Declare the link to be up. That may need to change later to make it dependent on the + WAN/Wireless modem. */ + rndis -> ux_slave_class_rndis_link_state = UX_DEVICE_CLASS_RNDIS_LINK_STATE_UP; + + /* Setup the physical address of this IP instance. */ + physical_address_msw = (ULONG)((rndis -> ux_slave_class_rndis_local_node_id[0] << 8) | (rndis -> ux_slave_class_rndis_local_node_id[1])); + physical_address_lsw = (ULONG)((rndis -> ux_slave_class_rndis_local_node_id[2] << 24) | (rndis -> ux_slave_class_rndis_local_node_id[3] << 16) | + (rndis -> ux_slave_class_rndis_local_node_id[4] << 8) | (rndis -> ux_slave_class_rndis_local_node_id[5])); + + /* Register this interface to the NetX USB interface broker. */ + _ux_network_driver_activate((VOID *) rndis, _ux_device_class_rndis_write, + &rndis -> ux_slave_class_rndis_network_handle, + physical_address_msw, + physical_address_lsw); + + /* Reset the endpoint buffers. */ + _ux_utility_memory_set(rndis -> ux_slave_class_rndis_bulkout_endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + _ux_utility_memory_set(rndis -> ux_slave_class_rndis_bulkin_endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + _ux_utility_memory_set(rndis -> ux_slave_class_rndis_interrupt_endpoint -> ux_slave_endpoint_transfer_request. + ux_slave_transfer_request_data_pointer, 0, UX_SLAVE_REQUEST_DATA_MAX_LENGTH); + + /* Resume the endpoint threads. */ + _ux_utility_thread_resume(&rndis -> ux_slave_class_rndis_interrupt_thread); + _ux_utility_thread_resume(&rndis -> ux_slave_class_rndis_bulkout_thread); + _ux_utility_thread_resume(&rndis -> ux_slave_class_rndis_bulkin_thread); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_ACTIVATE, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, rndis, 0, 0, 0) + + /* Return completion status. */ + return(UX_SUCCESS); + + } + else + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_ACTIVATE, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, rndis, 0, 0, 0) + + /* Return completion status. */ + return(UX_SUCCESS); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_bulkin_thread.c b/common/usbx_device_classes/src/ux_device_class_rndis_bulkin_thread.c new file mode 100644 index 0000000..2347b0c --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_bulkin_thread.c @@ -0,0 +1,223 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_bulkin_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the rndis bulkin endpoint. The bulk */ +/* IN endpoint is used when the device wants to write data to be sent */ +/* to the host. */ +/* */ +/* INPUT */ +/* */ +/* rndis_class Address of rndis class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_utility_event_flags_get Get event flags */ +/* _ux_utility_mutex_on Take mutex */ +/* _ux_utility_mutex_off Release mutex */ +/* _ux_utility_long_put Put 32-bit value */ +/* nx_packet_transmit_release Release NetX packet */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_rndis_bulkin_thread(ULONG rndis_class) +{ + +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_RNDIS *rndis; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; +ULONG actual_flags; +NX_PACKET *current_packet; +UCHAR *packet_header; +ULONG transfer_length; + + /* Cast properly the rndis instance. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_SLAVE_CLASS, rndis_class) + + /* Get the rndis instance from this class container. */ + rndis = (UX_SLAVE_CLASS_RNDIS *) class -> ux_slave_class_instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + + /* Get the transfer request for the bulk IN pip. */ + transfer_request = &rndis -> ux_slave_class_rndis_bulkin_endpoint -> ux_slave_endpoint_transfer_request; + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Wait until we have a event sent by the application. We do not treat yet the case where a timeout based + on the interrupt pipe frequency or a change in the idle state forces us to send an empty report. */ + status = _ux_utility_event_flags_get(&rndis -> ux_slave_class_rndis_event_flags_group, (UX_DEVICE_CLASS_RNDIS_NEW_BULKIN_EVENT | + UX_DEVICE_CLASS_RNDIS_NEW_DEVICE_STATE_CHANGE_EVENT), + TX_OR_CLEAR, &actual_flags, TX_WAIT_FOREVER); + + /* Check the completion code and the actual flags returned. */ + if (status == UX_SUCCESS && (actual_flags & UX_DEVICE_CLASS_RNDIS_NEW_DEVICE_STATE_CHANGE_EVENT) == 0) + { + + /* Parse all packets. */ + while(rndis -> ux_slave_class_rndis_xmit_queue != UX_NULL) + { + + /* Protect this thread. */ + _ux_utility_mutex_on(&rndis -> ux_slave_class_rndis_mutex); + + /* Get the current packet in the list. */ + current_packet = rndis -> ux_slave_class_rndis_xmit_queue; + + /* Set the next packet (or a NULL value) as the head of the xmit queue. */ + rndis -> ux_slave_class_rndis_xmit_queue = current_packet -> nx_packet_queue_next; + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&rndis -> ux_slave_class_rndis_mutex); + + /* If the link is down no need to rearm a packet. */ + if (rndis -> ux_slave_class_rndis_link_state == UX_DEVICE_CLASS_RNDIS_LINK_STATE_UP) + { + + /* Load the address of the current packet header at the physical header. */ + packet_header = current_packet -> nx_packet_prepend_ptr; + + /* Calculate the transfer length. */ + transfer_length = current_packet -> nx_packet_length + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH; + + /* Is there enough space for this packet in the transfer buffer? */ + if (transfer_length <= UX_SLAVE_REQUEST_DATA_MAX_LENGTH) + { + + /* Copy the packet in the transfer descriptor buffer. */ + _ux_utility_memory_copy (transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH, packet_header, current_packet -> nx_packet_length); + + /* Add the RNDIS header to this packet. */ + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG); + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_LENGTH, transfer_length); + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET, + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH - UX_DEVICE_CLASS_RNDIS_PACKET_DATA_OFFSET); + _ux_utility_long_put(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH, current_packet -> nx_packet_length); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_PACKET_TRANSMIT, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, transfer_length, UX_DEVICE_CLASS_RNDIS_ETHERNET_PACKET_SIZE); + + /* Check for error. */ + if (status != UX_SUCCESS) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + } + else + { + + /* No, there is not enough space. */ + + /* Report error to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + } + } + + /* Free the packet that was just sent. First do some housekeeping. */ + current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_DEVICE_CLASS_RNDIS_ETHERNET_SIZE; + current_packet -> nx_packet_length = current_packet -> nx_packet_length - UX_DEVICE_CLASS_RNDIS_ETHERNET_SIZE; + + /* And ask Netx to release it. */ + nx_packet_transmit_release(current_packet); + } + } + else + { + + /* We get here when the link is down or the last transmission failed. All packets pending must be freed. */ + while(rndis -> ux_slave_class_rndis_xmit_queue != UX_NULL) + { + + /* Protect the chain of packets. */ + _ux_utility_mutex_on(&rndis -> ux_slave_class_rndis_mutex); + + /* Get the current packet in the list. */ + current_packet = rndis -> ux_slave_class_rndis_xmit_queue; + + /* Set the next packet (or a NULL value) as the head of the xmit queue. */ + rndis -> ux_slave_class_rndis_xmit_queue = current_packet -> nx_packet_queue_next; + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&rndis -> ux_slave_class_rndis_mutex); + + /* Free the packet */ + current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_DEVICE_CLASS_RNDIS_ETHERNET_SIZE; + current_packet -> nx_packet_length = current_packet -> nx_packet_length - UX_DEVICE_CLASS_RNDIS_ETHERNET_SIZE; + + /* And ask Netx to release it. */ + nx_packet_transmit_release(current_packet); + } + } + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ + _ux_utility_thread_suspend(&rndis -> ux_slave_class_rndis_bulkin_thread); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_bulkout_thread.c b/common/usbx_device_classes/src/ux_device_class_rndis_bulkout_thread.c new file mode 100644 index 0000000..9bd016a --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_bulkout_thread.c @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_bulkout_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the rndis bulk out endpoint. It */ +/* is waiting for the host to send data on the bulk out endpoint to */ +/* the device. */ +/* */ +/* INPUT */ +/* */ +/* rndis_class Address of rndis class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_network_driver_packet_received Process received packet */ +/* _ux_utility_long_get Get 32-bit value */ +/* _ux_utility_thread_suspend Suspend thread */ +/* nx_packet_allocate Allocate NetX packet */ +/* nx_packet_release Release NetX packet */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_rndis_bulkout_thread(ULONG rndis_class) +{ + +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_RNDIS *rndis; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; +NX_PACKET *packet; +ULONG ip_given_length; +ULONG packet_payload; + + /* Cast properly the rndis instance. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_SLAVE_CLASS, rndis_class) + + /* Get the rndis instance from this class container. */ + rndis = (UX_SLAVE_CLASS_RNDIS *) class -> ux_slave_class_instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + + /* Select the transfer request associated with BULK OUT endpoint. */ + transfer_request = &rndis -> ux_slave_class_rndis_bulkout_endpoint -> ux_slave_endpoint_transfer_request; + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* We can accept new reception. Get a NX Packet. */ + status = nx_packet_allocate(&rndis -> ux_slave_class_rndis_packet_pool, &packet, + NX_RECEIVE_PACKET, MS_TO_TICK(UX_DEVICE_CLASS_RNDIS_PACKET_POOL_WAIT)); + + if (status == NX_SUCCESS) + { + + /* And length. */ + transfer_request -> ux_slave_transfer_request_requested_length = UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH; + transfer_request -> ux_slave_transfer_request_actual_length = 0; + + /* Memorize this packet at the beginning of the queue. */ + rndis -> ux_slave_class_rndis_receive_queue = packet; + + /* Reset the queue pointer of this packet. */ + packet -> nx_packet_queue_next = UX_NULL; + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH, + UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH + UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH); + + /* Check the completion code. */ + if (status == UX_SUCCESS) + { + + /* We only proceed with packets that are received OK, if error, ignore the packet. */ + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_PACKET_RECEIVE, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Check the state of the transfer. If there is an error, we do not proceed with this report. Also ensure the header has a valid ID of 1. */ + if (_ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_MESSAGE_TYPE) == UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_MSG) + { + + /* Ensure this packet is at least larger than the header. */ + if (transfer_request -> ux_slave_transfer_request_actual_length > UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH) + { + + /* Get the size of the payload. */ + packet_payload = _ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_DATA_LENGTH); + + /* Ensure the length reported in the RNDIS header is not larger than it actually is. + The reason we can't check to see if the length reported in the header and the + actual length are exactly equal is because there might other data after the payload + (padding, or even a message). */ + if (packet_payload <= transfer_request -> ux_slave_transfer_request_actual_length - UX_DEVICE_CLASS_RNDIS_PACKET_HEADER_LENGTH) + { + + /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ + packet -> nx_packet_prepend_ptr += sizeof(USHORT); + + /* Adjust the prepend, length, and append fields. */ + packet -> nx_packet_length = packet_payload; + packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + packet_payload; + + + /* Copy the received packet in the IP packet data area. */ + _ux_utility_memory_copy(packet -> nx_packet_prepend_ptr, transfer_request -> ux_slave_transfer_request_data_pointer + UX_DEVICE_CLASS_RNDIS_PACKET_BUFFER, packet_payload); + + /* Calculate the accurate packet length from ip header */ + if((*(packet -> nx_packet_prepend_ptr + 12) == 0x08) && + (*(packet -> nx_packet_prepend_ptr + 13) == 0)) + { + + ip_given_length = _ux_utility_short_get_big_endian(packet -> nx_packet_prepend_ptr + 16) + UX_DEVICE_CLASS_RNDIS_ETHERNET_SIZE; + packet -> nx_packet_length = ip_given_length ; + packet -> nx_packet_append_ptr = packet -> nx_packet_prepend_ptr + ip_given_length; + } + + /* Send that packet to the NetX USB broker. */ + _ux_network_driver_packet_received(rndis -> ux_slave_class_rndis_network_handle, packet); + } + else + + /* We received a malformed packet. Report to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + } + else + + /* We received a malformed packet. Report to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + } + } + else + + /* Free the packet that was not successfully received. */ + nx_packet_release(packet); + } + else + { + + /* Packet allocation timed out. Note that the timeout value is + configurable. */ + + /* Error trap. No need for trace, since NetX does it. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + } + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ + _ux_utility_thread_suspend(&rndis -> ux_slave_class_rndis_bulkout_thread); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_control_request.c b/common/usbx_device_classes/src/ux_device_class_rndis_control_request.c new file mode 100644 index 0000000..b7ed5b1 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_control_request.c @@ -0,0 +1,200 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_control_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* rndis Pointer to rndis class */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_endpoint_stall Endpoint stall */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_memory_set Set memory */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_long_get Get 32-bit value */ +/* _ux_utility_event_flags_set Set event flags */ +/* _ux_device_class_rndis_msg_initialize Command initialize */ +/* _ux_device_class_rndis_msg_query Command query */ +/* _ux_device_class_rndis_msg_set Command set */ +/* _ux_device_class_rndis_msg_reset Command reset */ +/* _ux_device_class_rndis_msg_keep_alive Command keep alive */ +/* */ +/* CALLED BY */ +/* */ +/* RNDIS Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_rndis_control_request(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_TRANSFER *transfer_request_in; +UX_SLAVE_DEVICE *device; +ULONG request; +ULONG request_length; +ULONG rndis_command; +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_RNDIS *rndis; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the pointer to the transfer request associated with the control endpoint. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Extract all necessary fields of the request. */ + request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST); + request_length = _ux_utility_short_get(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_LENGTH); + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the rndis instance from this class container. */ + rndis = (UX_SLAVE_CLASS_RNDIS *) class -> ux_slave_class_instance; + + /* Here we proceed only the standard request we know of at the device level. */ + switch (request) + { + + + case UX_DEVICE_CLASS_RNDIS_SEND_ENCAPSULATED_COMMAND : + + + /* We have received a command. Check if the command is valid and dispatch it. */ + rndis_command = _ux_utility_long_get(transfer_request -> ux_slave_transfer_request_data_pointer); + + switch (rndis_command) + { + + case UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE : + + _ux_device_class_rndis_msg_initialize(rndis, transfer_request); + break; + + case UX_DEVICE_CLASS_RNDIS_MSG_HALT : + break; + + + case UX_DEVICE_CLASS_RNDIS_MSG_QUERY : + _ux_device_class_rndis_msg_query(rndis, transfer_request); + break; + + + case UX_DEVICE_CLASS_RNDIS_MSG_SET : + _ux_device_class_rndis_msg_set(rndis, transfer_request); + break; + + + case UX_DEVICE_CLASS_RNDIS_MSG_RESET : + _ux_device_class_rndis_msg_reset(rndis, transfer_request); + break; + + + case UX_DEVICE_CLASS_RNDIS_MSG_INDICATE_STATUS : + break; + + + case UX_DEVICE_CLASS_RNDIS_MSG_KEEP_ALIVE : + _ux_device_class_rndis_msg_keep_alive(rndis, transfer_request); + break; + + default : + + /* Unknown function. Stall the endpoint. */ + _ux_device_stack_endpoint_stall(&device -> ux_slave_device_control_endpoint); + break; + + } + + /* Check the return status. If no error, we set the interrupt pipe to reply response available. + All RNDIS events are on the interrupt endpoint IN, from the host. */ + transfer_request_in = &rndis -> ux_slave_class_rndis_interrupt_endpoint -> ux_slave_endpoint_transfer_request; + + /* Reset the buffer. */ + _ux_utility_memory_set(transfer_request_in -> ux_slave_transfer_request_data_pointer, 0, UX_DEVICE_CLASS_RNDIS_INTERRUPT_RESPONSE_LENGTH); + + /* Set the buffer of this transfer request with the flag for response available. */ + transfer_request_in -> ux_slave_transfer_request_data_pointer[0] = UX_DEVICE_CLASS_RNDIS_INTERRUPT_RESPONSE_AVAILABLE_FLAG; + + /* Set an event to wake up the interrupt thread. */ + _ux_utility_event_flags_set(&rndis -> ux_slave_class_rndis_event_flags_group, UX_DEVICE_CLASS_RNDIS_NEW_INTERRUPT_EVENT, TX_OR); + + break; + + case UX_DEVICE_CLASS_RNDIS_GET_ENCAPSULATED_RESPONSE : + + + /* Copy the response into the request data buffer. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, rndis -> ux_slave_class_rndis_response, + rndis -> ux_slave_class_rndis_response_length); + + /* Set the phase of the transfer to data out. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* We can return the RNDIS response. */ + _ux_device_stack_transfer_request(transfer_request, rndis -> ux_slave_class_rndis_response_length, request_length); + + break ; + + default: + + /* Unknown function. It's not handled. */ + return(UX_ERROR); + } + + /* It's handled. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_deactivate.c b/common/usbx_device_classes/src/ux_device_class_rndis_deactivate.c new file mode 100644 index 0000000..c47748c --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_deactivate.c @@ -0,0 +1,129 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivate an instance of the rndis class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_all_request_abort */ +/* Abort all transfers */ +/* _ux_utility_event_flags_set Set event flags */ +/* _ux_network_driver_deactivate Deactivate NetX USB interface */ +/* */ +/* CALLED BY */ +/* */ +/* RNDIS Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_rndis_deactivate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_RNDIS *rndis; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + rndis = (UX_SLAVE_CLASS_RNDIS *) class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. Normally the interface can be derived + from the class instance but since RNDIS has 2 interfaces and we only store the Control + interface in the class container, we used the class_command pointer to retrieve the + correct interface which issued the deactivation. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Check if this is the Control or Data interface. We only need to dismount the link and abort the + transfer once for the 2 classes. */ + if (interface -> ux_slave_interface_descriptor.bInterfaceClass == UX_DEVICE_CLASS_RNDIS_CLASS_COMMUNICATION_CONTROL) + { + + /* Declare the link to be down. That may nd to change later to make it dependant on the + WAN/Wireless modem. */ + rndis -> ux_slave_class_rndis_link_state = UX_DEVICE_CLASS_RNDIS_LINK_STATE_DOWN; + + /* Terminate the transactions pending on the endpoints (interrupt, bulk in, bulk out). */ + _ux_device_stack_transfer_all_request_abort(rndis -> ux_slave_class_rndis_interrupt_endpoint, UX_TRANSFER_BUS_RESET); + _ux_device_stack_transfer_all_request_abort(rndis -> ux_slave_class_rndis_bulkin_endpoint, UX_TRANSFER_BUS_RESET); + _ux_device_stack_transfer_all_request_abort(rndis -> ux_slave_class_rndis_bulkout_endpoint, UX_TRANSFER_BUS_RESET); + + /* We have 2 threads waiting for an event, interrupt and bulk in. We wake them up with + a DEVICE_STATE_CHANGE event. In turn they will release the NetX resources used and suspend. */ + _ux_utility_event_flags_set(&rndis -> ux_slave_class_rndis_event_flags_group, UX_DEVICE_CLASS_RNDIS_NEW_DEVICE_STATE_CHANGE_EVENT, TX_OR); + + /* If there is a deactivate function call it. */ + if (rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_instance_deactivate != UX_NULL) + + /* Invoke the application. */ + rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_instance_deactivate(rndis); + + /* Deregister this interface to the NetX USB interface broker. */ + _ux_network_driver_deactivate((VOID *) rndis, rndis -> ux_slave_class_rndis_network_handle); + + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_DEACTIVATE, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(rndis); + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_entry.c b/common/usbx_device_classes/src/ux_device_class_rndis_entry.c new file mode 100644 index 0000000..c8199b9 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_entry.c @@ -0,0 +1,142 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_class_device_rndis_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the rndis class. It */ +/* will be called by the device stack enumeration module when the */ +/* host has sent a SET_CONFIGURATION command and the rndis interface */ +/* needs to be mounted. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_rndis_initialize Initialize rndis class */ +/* _ux_device_class_rndis_activate Activate rndis class */ +/* _ux_device_class_rndis_deactivate Deactivate rndis class */ +/* _ux_device_class_rndis_control_request Request control */ +/* */ +/* CALLED BY */ +/* */ +/* RNDIS Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_rndis_entry(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_slave_class_command_request) + { + + case UX_SLAVE_CLASS_COMMAND_INITIALIZE: + + /* Call the init function of the RNDIS class. */ + status = _ux_device_class_rndis_initialize(command); + + /* Return the completion status. */ + return(status); + + + case UX_SLAVE_CLASS_COMMAND_QUERY: + + /* Check the CLASS definition in the interface descriptor. */ + if (command -> ux_slave_class_command_class == UX_DEVICE_CLASS_RNDIS_CLASS_COMMUNICATION_CONTROL || + command -> ux_slave_class_command_class == UX_DEVICE_CLASS_RNDIS_CLASS_COMMUNICATION_DATA) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_SLAVE_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the host has sent a SET_CONFIGURATION command + and this interface has to be mounted. Both Bulk endpoints have to be mounted + and the rndis thread needs to be activated. */ + status = _ux_device_class_rndis_activate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted. + The device endpoints have to be dismounted and the rndis thread canceled. */ + status = _ux_device_class_rndis_deactivate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_REQUEST: + + /* The request command is used when the host sends a command on the control endpoint. */ + status = _ux_device_class_rndis_control_request(command); + + /* Return the completion status. */ + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_initialize.c b/common/usbx_device_classes/src/ux_device_class_rndis_initialize.c new file mode 100644 index 0000000..43eab26 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_initialize.c @@ -0,0 +1,367 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + +UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT + +/* Define list of supported OIDs (ends with zero-terminator) */ +ULONG ux_device_class_rndis_oid_supported_list[UX_DEVICE_CLASS_RNDIS_OID_SUPPORTED_LIST_LENGTH + 1] = +{ + /* Mandatory general OIDs. */ + UX_DEVICE_CLASS_RNDIS_OID_GEN_SUPPORTED_LIST, + UX_DEVICE_CLASS_RNDIS_OID_GEN_HARDWARE_STATUS, + UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_SUPPORTED, + UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_IN_USE, + UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE, + UX_DEVICE_CLASS_RNDIS_OID_GEN_LINK_SPEED, + UX_DEVICE_CLASS_RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE, + UX_DEVICE_CLASS_RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE, + UX_DEVICE_CLASS_RNDIS_OID_GEN_VENDOR_ID, + UX_DEVICE_CLASS_RNDIS_OID_GEN_VENDOR_DESCRIPTION, + UX_DEVICE_CLASS_RNDIS_OID_GEN_VENDOR_DRIVER_VERSION, + UX_DEVICE_CLASS_RNDIS_OID_GEN_CURRENT_PACKET_FILTER, + UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE, + UX_DEVICE_CLASS_RNDIS_OID_GEN_MAC_OPTIONS, + UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, + UX_DEVICE_CLASS_RNDIS_OID_GEN_PHYSICAL_MEDIUM, + UX_DEVICE_CLASS_RNDIS_OID_GEN_RNDIS_CONFIG_PARAMETER, + + /* Mandatory statistical OIDs. */ + UX_DEVICE_CLASS_RNDIS_OID_GEN_XMIT_OK, + UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_OK, + UX_DEVICE_CLASS_RNDIS_OID_GEN_XMIT_ERROR, + UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_ERROR, + UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_NO_BUFFER, + + /* Mandatory 802.3 OIDs. */ + UX_DEVICE_CLASS_RNDIS_OID_802_3_PERMANENT_ADDRESS, + UX_DEVICE_CLASS_RNDIS_OID_802_3_CURRENT_ADDRESS, + UX_DEVICE_CLASS_RNDIS_OID_802_3_MULTICAST_LIST, + UX_DEVICE_CLASS_RNDIS_OID_802_3_MAC_OPTIONS, + UX_DEVICE_CLASS_RNDIS_OID_802_3_MAXIMUM_LIST_SIZE, + + /* Mandatory 802.3 statistical OIDs. */ + UX_DEVICE_CLASS_RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT, + UX_DEVICE_CLASS_RNDIS_OID_802_3_XMIT_ONE_COLLISION, + UX_DEVICE_CLASS_RNDIS_OID_802_3_XMIT_MORE_COLLISIONS, + + 0, +}; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB RNDIS device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to rndis command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_event_flags_create Create Flag group */ +/* _ux_utility_event_flags_delete Delete Flag group */ +/* _ux_utility_mutex_create Create mutex */ +/* _ux_utility_mutex_delete Delete mutex */ +/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_utility_thread_create Create thread */ +/* _ux_utility_thread_delete Delete thread */ +/* nx_packet_pool_create Create NetX packet pool */ +/* nx_packet_pool_delete Delete NetX packet pool */ +/* */ +/* CALLED BY */ +/* */ +/* USBX Source Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_rndis_initialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_RNDIS *rndis; +UX_SLAVE_CLASS_RNDIS_PARAMETER *rndis_parameter; +UX_SLAVE_CLASS *class; +UINT status; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Create an instance of the device rndis class. */ + rndis = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_RNDIS)); + + /* Check for successful allocation. */ + if (rndis == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save the address of the RNDIS instance inside the RNDIS container. */ + class -> ux_slave_class_instance = (VOID *) rndis; + + /* Get the pointer to the application parameters for the rndis class. */ + rndis_parameter = command -> ux_slave_class_command_parameter; + + /* Store the start and stop signals if needed by the application. */ + rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_instance_activate = rndis_parameter -> ux_slave_class_rndis_instance_activate; + rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_instance_deactivate = rndis_parameter -> ux_slave_class_rndis_instance_deactivate; + + /* Save the Netx IP passed by the application. */ + rndis -> ux_slave_class_rndis_nx_ip = rndis_parameter -> ux_slave_class_rndis_parameter_nx_ip; + + /* Save the Netx IP address passed by the application. */ + rndis -> ux_slave_class_rndis_nx_ip_address = rndis_parameter -> ux_slave_class_rndis_parameter_nx_ip_address; + + /* Save the Netx IP address network mask passed by the application. */ + rndis -> ux_slave_class_rndis_nx_ip_network_mask = rndis_parameter -> ux_slave_class_rndis_parameter_nx_ip_network_mask; + + /* Copy the local node ID. */ + _ux_utility_memory_copy(rndis -> ux_slave_class_rndis_local_node_id, rndis_parameter -> ux_slave_class_rndis_parameter_local_node_id, + UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH); + + /* Copy the remote node ID. */ + _ux_utility_memory_copy(rndis -> ux_slave_class_rndis_remote_node_id, rndis_parameter -> ux_slave_class_rndis_parameter_remote_node_id, + UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH); + + /* Store the rest of the parameters as they are in the local instance. */ + _ux_utility_memory_copy(&rndis -> ux_slave_class_rndis_parameter, rndis_parameter, sizeof (UX_SLAVE_CLASS_RNDIS_PARAMETER)); + + /* Create a mutex to protect the RNDIS thread and the application messing up the transmit queue. */ + status = _ux_utility_mutex_create(&rndis -> ux_slave_class_rndis_mutex, "ux_slave_class_rndis_mutex"); + if (status != UX_SUCCESS) + status = UX_MUTEX_ERROR; + + /* Allocate some memory for the interrupt thread stack. */ + if (status == UX_SUCCESS) + { + rndis -> ux_slave_class_rndis_interrupt_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (rndis -> ux_slave_class_rndis_interrupt_thread_stack == UX_NULL) + + /* Set status to memory insufficient. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Interrupt endpoint treatment needs to be running in a different thread. So start + a new thread. We pass a pointer to the rndis instance to the new thread. This thread + does not start until we have a instance of the class. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_thread_create(&rndis -> ux_slave_class_rndis_interrupt_thread , "ux_slave_class_rndis_interrupt_thread", + _ux_device_class_rndis_interrupt_thread, + (ULONG) (ALIGN_TYPE) class, (VOID *) rndis -> ux_slave_class_rndis_interrupt_thread_stack , + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_DONT_START); + + /* Check the creation of this thread. */ + if (status != UX_SUCCESS) + status = UX_THREAD_ERROR; + } + + UX_THREAD_EXTENSION_PTR_SET(&(rndis -> ux_slave_class_rndis_interrupt_thread), class) + + /* Allocate some memory for the bulk out thread stack. */ + if (status == UX_SUCCESS) + { + rndis -> ux_slave_class_rndis_bulkout_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (rndis -> ux_slave_class_rndis_bulkout_thread_stack == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Bulk endpoint treatment needs to be running in a different thread. So start + a new thread. We pass a pointer to the rndis instance to the new thread. This thread + does not start until we have a instance of the class. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_thread_create(&rndis -> ux_slave_class_rndis_bulkout_thread , "ux_slave_class_rndis_bulkout_thread", + _ux_device_class_rndis_bulkout_thread, + (ULONG) (ALIGN_TYPE) class, (VOID *) rndis -> ux_slave_class_rndis_bulkout_thread_stack , + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_DONT_START); + + /* Check the creation of this thread. */ + if (status != UX_SUCCESS) + status = UX_THREAD_ERROR; + } + + UX_THREAD_EXTENSION_PTR_SET(&(rndis -> ux_slave_class_rndis_bulkout_thread), class) + + /* Allocate some memory for the bulk in thread stack. */ + if (status == UX_SUCCESS) + { + rndis -> ux_slave_class_rndis_bulkin_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check for successful allocation. */ + if (rndis -> ux_slave_class_rndis_bulkin_thread_stack == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Bulk endpoint treatment needs to be running in a different thread. So start + a new thread. We pass a pointer to the rndis instance to the new thread. This thread + does not start until we have a instance of the class. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_thread_create(&rndis -> ux_slave_class_rndis_bulkin_thread , "ux_slave_class_rndis_bulkin_thread", + _ux_device_class_rndis_bulkin_thread, + (ULONG) (ALIGN_TYPE) class, (VOID *) rndis -> ux_slave_class_rndis_bulkin_thread_stack , + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_DONT_START); + + /* Check the creation of this thread. */ + if (status != UX_SUCCESS) + status = UX_THREAD_ERROR; + } + + UX_THREAD_EXTENSION_PTR_SET(&(rndis -> ux_slave_class_rndis_bulkin_thread), class) + + /* Create a event flag group for the rndis class to synchronize with the event interrupt thread. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_event_flags_create(&rndis -> ux_slave_class_rndis_event_flags_group, "ux_device_class_rndis_event_flag"); + + /* Check status. */ + if (status != UX_SUCCESS) + status = UX_EVENT_ERROR; + } + + /* Allocate some packet pool for reception. */ + if (status == UX_SUCCESS) + { + + /* UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE overflow has been checked by + * UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT outside of function. + */ + rndis -> ux_slave_class_rndis_pool_memory = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE); + + /* Check the completion status. */ + if (rndis -> ux_slave_class_rndis_pool_memory == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Create a packet pool. */ + if (status == UX_SUCCESS) + { + status = nx_packet_pool_create(&rndis -> ux_slave_class_rndis_packet_pool, "Rndis Device Packet Pool", + UX_DEVICE_CLASS_RNDIS_NX_PAYLOAD_SIZE, rndis -> ux_slave_class_rndis_pool_memory, UX_DEVICE_CLASS_RNDIS_NX_ETHERNET_POOL_ALLOCSIZE); + + /* Check for pool creation error. */ + if (status != UX_SUCCESS) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Create a semaphore for protecting the driver entry. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&rndis -> ux_slave_class_rndis_semaphore, "ux_device_class_rndis_semaphore", 1); + if (status == UX_SUCCESS) + + /* Return success. */ + return(UX_SUCCESS); + + /* Semaphore creation error. */ + status = UX_SEMAPHORE_ERROR; + } + + /* Failed! Free up resources. */ + + /* Delete semaphore for protecting the driver entry. */ + if (rndis -> ux_slave_class_rndis_semaphore.tx_semaphore_id != 0) + _ux_utility_semaphore_delete(&rndis -> ux_slave_class_rndis_semaphore); + + /* Delete the packet pool. */ + if (rndis -> ux_slave_class_rndis_packet_pool.nx_packet_pool_id != 0) + nx_packet_pool_delete(&rndis -> ux_slave_class_rndis_packet_pool); + + /* Free rndis -> ux_slave_class_rndis_pool_memory. */ + if (rndis -> ux_slave_class_rndis_pool_memory) + _ux_utility_memory_free(rndis -> ux_slave_class_rndis_pool_memory); + + /* Delete rndis -> ux_slave_class_rndis_event_flags_group. */ + if (rndis -> ux_slave_class_rndis_event_flags_group.tx_event_flags_group_id != 0) + _ux_utility_event_flags_delete(&rndis -> ux_slave_class_rndis_event_flags_group); + + /* Delete rndis -> ux_slave_class_rndis_bulkin_thread. */ + if (rndis -> ux_slave_class_rndis_bulkin_thread.tx_thread_id != 0) + _ux_utility_thread_delete(&rndis -> ux_slave_class_rndis_bulkin_thread); + + /* Free rndis -> ux_slave_class_rndis_bulkin_thread_stack. */ + if (rndis -> ux_slave_class_rndis_bulkin_thread_stack) + _ux_utility_memory_free(rndis -> ux_slave_class_rndis_bulkin_thread_stack); + + /* Delete rndis -> ux_slave_class_rndis_bulkout_thread. */ + if (rndis -> ux_slave_class_rndis_bulkout_thread.tx_thread_id != 0) + _ux_utility_thread_delete(&rndis -> ux_slave_class_rndis_bulkout_thread); + + /* Free rndis -> ux_slave_class_rndis_bulkout_thread_stack. */ + if (rndis -> ux_slave_class_rndis_bulkout_thread_stack) + _ux_utility_memory_free(rndis -> ux_slave_class_rndis_bulkout_thread_stack); + + /* Delete rndis -> ux_slave_class_rndis_interrupt_thread. */ + if (rndis -> ux_slave_class_rndis_interrupt_thread.tx_thread_id != 0) + _ux_utility_thread_delete(&rndis -> ux_slave_class_rndis_interrupt_thread); + + /* Free rndis -> ux_slave_class_rndis_interrupt_thread_stack. */ + if (rndis -> ux_slave_class_rndis_interrupt_thread_stack) + _ux_utility_memory_free(rndis -> ux_slave_class_rndis_interrupt_thread_stack); + + /* Delete rndis -> ux_slave_class_rndis_mutex. */ + if (rndis -> ux_slave_class_rndis_mutex.tx_mutex_id != 0) + _ux_utility_mutex_delete(&rndis -> ux_slave_class_rndis_mutex); + + /* Free memory for rndis instance. */ + _ux_utility_memory_free(rndis); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_interrupt_thread.c b/common/usbx_device_classes/src/ux_device_class_rndis_interrupt_thread.c new file mode 100644 index 0000000..01e3463 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_interrupt_thread.c @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_interrupt_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the rndis interrupt endpoint */ +/* */ +/* INPUT */ +/* */ +/* rndis_class Address of rndis class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Request transfer */ +/* _ux_utility_event_flags_get Get event flags */ +/* _ux_utility_thread_suspend Suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_rndis_interrupt_thread(ULONG rndis_class) +{ + +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_RNDIS *rndis; +UX_SLAVE_DEVICE *device; +UX_SLAVE_TRANSFER *transfer_request; +UINT status; +ULONG actual_flags; + + /* Cast properly the rndis instance. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_SLAVE_CLASS, rndis_class) + + /* Get the rndis instance from this class container. */ + rndis = (UX_SLAVE_CLASS_RNDIS *) class -> ux_slave_class_instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + + /* All RNDIS events are on the interrupt endpoint IN, from the host. */ + transfer_request = &rndis -> ux_slave_class_rndis_interrupt_endpoint -> ux_slave_endpoint_transfer_request; + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + + /* Wait until we have a event sent by the application. We do not treat yet the case where a timeout based + on the interrupt pipe frequency or a change in the idle state forces us to send an empty report. */ + status = _ux_utility_event_flags_get(&rndis -> ux_slave_class_rndis_event_flags_group, (UX_DEVICE_CLASS_RNDIS_NEW_INTERRUPT_EVENT | + UX_DEVICE_CLASS_RNDIS_NEW_DEVICE_STATE_CHANGE_EVENT), + TX_OR_CLEAR, &actual_flags, TX_WAIT_FOREVER); + + /* If error log is enabled, insert this error message into the log buffer. */ + + /* Check the completion code. */ + if (status == UX_SUCCESS && (actual_flags & UX_DEVICE_CLASS_RNDIS_NEW_DEVICE_STATE_CHANGE_EVENT) == 0) + { + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, UX_DEVICE_CLASS_RNDIS_INTERRUPT_RESPONSE_LENGTH, + UX_DEVICE_CLASS_RNDIS_INTERRUPT_RESPONSE_LENGTH); + + /* Check error code. */ + if (status != UX_SUCCESS) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + } + } + + /* We need to suspend ourselves. We will be resumed by the device enumeration module. */ + _ux_utility_thread_suspend(&rndis -> ux_slave_class_rndis_interrupt_thread); + + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_msg_initialize.c b/common/usbx_device_classes/src/ux_device_class_rndis_msg_initialize.c new file mode 100644 index 0000000..6e1c7c3 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_msg_initialize.c @@ -0,0 +1,142 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_msg_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function analyzes and replies to the MSG INITIALIZE */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* rndis Pointer to rndis class */ +/* transfer_request Pointer to the transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_long_get Get 32-bit value */ +/* _ux_utility_long_put Put 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* RNDIS Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_rndis_msg_initialize(UX_SLAVE_CLASS_RNDIS *rndis, UX_SLAVE_TRANSFER *transfer_request) +{ + +UCHAR *rndis_msg; +UCHAR *rndis_response; + + /* Get the pointer to the RNDIS message. */ + rndis_msg = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Get the request ID and keep it for the response. */ + rndis -> ux_slave_class_rndis_request_id = _ux_utility_long_get(rndis_msg + UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE_REQUEST_ID); + + /* Get the major version and store it into the RNDIS instance. */ + rndis -> ux_slave_class_rndis_major_version = _ux_utility_long_get(rndis_msg + UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE_MAJOR_VERSION); + + /* Get the minor version and store it into the RNDIS instance. */ + rndis -> ux_slave_class_rndis_minor_version = _ux_utility_long_get(rndis_msg + UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE_MINOR_VERSION); + + /* Get the max transfer size and store it into the RNDIS instance. */ + rndis -> ux_slave_class_rndis_max_transfer_size = _ux_utility_long_get(rndis_msg + UX_DEVICE_CLASS_RNDIS_MSG_INITIALIZE_MAX_TRANSFER_SIZE); + + /* Store the state machine to initialized. */ + rndis -> ux_slave_class_rndis_state = UX_DEVICE_CLASS_RNDIS_STATE_INITIALIZED; + + /* Now prepare the response. */ + rndis_response = rndis -> ux_slave_class_rndis_response; + + /* First store the command. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE); + + /* Then the length of the response. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MESSAGE_LENGTH, UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_RESPONSE_LENGTH); + + /* Store the request ID. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_REQUEST_ID, rndis -> ux_slave_class_rndis_request_id); + + /* Force the status to SUCCESS. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_STATUS, UX_DEVICE_CLASS_RNDIS_STATUS_SUCCESS); + + /* Set the major version of the device */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MAJOR_VERSION, UX_DEVICE_CLASS_RNDIS_VERSION_MAJOR); + + /* Set the minor version of the device */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MINOR_VERSION, UX_DEVICE_CLASS_RNDIS_VERSION_MINOR); + + /* Set the type of connection supported. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_DEVICE_FLAGS, UX_DEVICE_CLASS_RNDIS_DF_CONNECTION_SUPPORTED); + + /* Set the type of media supported. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MEDIUM, UX_DEVICE_CLASS_RNDIS_MEDIUM_SUPPORTED); + + /* Set the max packet per transfer. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MAX_PACKETS_PER_TRANSFER, UX_DEVICE_CLASS_RNDIS_MAX_PACKET_PER_TRANSFER); + + /* Set the max transfer size. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_MAX_TRANSFER_SIZE, UX_DEVICE_CLASS_RNDIS_MAX_PACKET_TRANSFER_SIZE); + + /* Set the packet alignment factor. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_PACKET_ALIGNMENT, UX_DEVICE_CLASS_RNDIS_PACKET_ALIGNEMENT_FACTOR); + + /* Set AFListOffset and AFListSize fields to 0. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_AFL_LIST_OFFSET, 0); + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_AFL_LIST_SIZE, 0); + + /* Set the response length. */ + rndis -> ux_slave_class_rndis_response_length = UX_DEVICE_CLASS_RNDIS_CMPLT_INITIALIZE_RESPONSE_LENGTH; + + /* We are done. Return UX_SUCCESS. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_msg_keep_alive.c b/common/usbx_device_classes/src/ux_device_class_rndis_msg_keep_alive.c new file mode 100644 index 0000000..ad0abd0 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_msg_keep_alive.c @@ -0,0 +1,107 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_msg_keep_alive PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function analyzes and replies to the MSG KEEP_ALIVE */ +/* */ +/* INPUT */ +/* */ +/* rndis Pointer to rndis class */ +/* transfer_request Pointer to the transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_long_get Get 32-bit value */ +/* _ux_utility_long_put Put 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* RNDIS Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_rndis_msg_keep_alive(UX_SLAVE_CLASS_RNDIS *rndis, UX_SLAVE_TRANSFER *transfer_request) +{ + +UCHAR *rndis_msg; +UCHAR *rndis_response; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_MSG_KEEP_ALIVE, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Get the pointer to the RNDIS message. */ + rndis_msg = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Get the request ID and keep it for the response. */ + rndis -> ux_slave_class_rndis_request_id = _ux_utility_long_get(rndis_msg + UX_DEVICE_CLASS_RNDIS_MSG_KEEP_ALIVE_REQUEST_ID); + + /* Now prepare the response. */ + rndis_response = rndis -> ux_slave_class_rndis_response; + + /* First store the command. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE); + + /* Then the length of the response. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_MESSAGE_LENGTH, UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_RESPONSE_LENGTH); + + /* Store the request ID. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_REQUEST_ID, rndis -> ux_slave_class_rndis_request_id); + + /* Force the status to SUCCESS. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_STATUS, UX_DEVICE_CLASS_RNDIS_STATUS_SUCCESS); + + /* Set the response length. */ + rndis -> ux_slave_class_rndis_response_length = UX_DEVICE_CLASS_RNDIS_CMPLT_KEEP_ALIVE_RESPONSE_LENGTH; + + /* We are done. Return UX_SUCCESS. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_msg_query.c b/common/usbx_device_classes/src/ux_device_class_rndis_msg_query.c new file mode 100644 index 0000000..a2b6b33 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_msg_query.c @@ -0,0 +1,357 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_msg_query PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function analyzes and replies to the MSG QUERY */ +/* */ +/* INPUT */ +/* */ +/* rndis Pointer to rndis class */ +/* transfer_request Pointer to the transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_long_get Get 32-bit value */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_string_length_check Check and return C string length */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* RNDIS Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_rndis_msg_query(UX_SLAVE_CLASS_RNDIS *rndis, UX_SLAVE_TRANSFER *transfer_request) +{ + +UCHAR *rndis_msg; +UCHAR *rndis_response; +ULONG rndis_oid; +ULONG rndis_response_length; +UINT rndis_response_string_length = 0; +ULONG oid_index; +ULONG status; + + /* Get the pointer to the RNDIS message. */ + rndis_msg = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Get the request ID and keep it for the response. */ + rndis -> ux_slave_class_rndis_request_id = _ux_utility_long_get(rndis_msg + UX_DEVICE_CLASS_RNDIS_MSG_QUERY_REQUEST_ID); + + /* Get the OID. */ + rndis_oid = _ux_utility_long_get(rndis_msg + UX_DEVICE_CLASS_RNDIS_MSG_QUERY_OID); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_MSG_QUERY, rndis, rndis_oid, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Now prepare the response. */ + rndis_response = rndis -> ux_slave_class_rndis_response; + + /* First store the command. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY); + + /* Store the request ID. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_REQUEST_ID, rndis -> ux_slave_class_rndis_request_id); + + /* By default the function will succeed. */ + status = UX_DEVICE_CLASS_RNDIS_STATUS_SUCCESS; + + /* What OID are we dealing here ? */ + switch (rndis_oid) + { + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_SUPPORTED_LIST : + + /* Supported List of OIDs. Parse each OID until the end and store it in the response buffer. */ + oid_index = 0; + while (ux_device_class_rndis_oid_supported_list[oid_index] != 0) + { + + /* We have found a valid OID to return. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER + (oid_index * sizeof(ULONG)), + ux_device_class_rndis_oid_supported_list[oid_index]); + + /* Next OID index. */ + oid_index++; + + } + + /* Set the total response length. */ + rndis_response_length = oid_index * (ULONG)sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE : + + /* Set the maximum frame size. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MAX_FRAME_SIZE); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_SUPPORTED : + + /* Set the media supported. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MEDIA_802_3); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_IN_USE : + + /* Set the media in use. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MEDIA_802_3); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_HARDWARE_STATUS : + + /* Set the hardware status. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_OID_HW_STATUS_READY); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_PHYSICAL_MEDIUM : + + /* Set the physical medium. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, 0); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE : + + /* Set the physical medium. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MAX_PACKET_LENGTH); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_LINK_SPEED : + + /* Set the link speed. For now we assume a full speed device. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_LINK_SPEED_FS); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_CONNECT_STATUS : + + /* Set the media connection status. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MEDIA_CONNECTED); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_MAC_OPTIONS : + + /* Set the MAC options. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, UX_DEVICE_CLASS_RNDIS_MAC_OPTIONS); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_VENDOR_ID : + + /* Set the vendor ID. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_parameter_vendor_id); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_DRIVER_VERSION : + + /* Set the driver version. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_parameter_driver_version); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_VENDOR_DESCRIPTION : + + /* Get the string length for the vendor description. */ + status = _ux_utility_string_length_check(rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_parameter_vendor_description, &rndis_response_string_length, UX_DEVICE_CLASS_RNDIS_VENDOR_DESCRIPTION_MAX_LENGTH); + if (status) + return(status); + + /* Set the total response length. */ + rndis_response_length = (ULONG) rndis_response_string_length; + + /* Copy the vendor description. */ + _ux_utility_memory_copy(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_parameter.ux_slave_class_rndis_parameter_vendor_description, rndis_response_length); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_XMIT_OK : + + /* Set the appropriate statistic value. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_statistics_xmit_ok); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_OK : + + /* Set the appropriate statistic value. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_statistics_rcv_ok); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_XMIT_ERROR : + + /* Set the appropriate statistic value. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_statistics_xmit_error); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_ERROR : + + /* Set the appropriate statistic value. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_statistics_rcv_error); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_NO_BUFFER : + + /* Set the appropriate statistic value. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, rndis -> ux_slave_class_rndis_statistics_rcv_no_buffer); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + case UX_DEVICE_CLASS_RNDIS_OID_802_3_CURRENT_ADDRESS : + + + /* Save the Hardware address in the return message. */ + _ux_utility_memory_copy(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, + rndis -> ux_slave_class_rndis_remote_node_id, UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH); + + /* Set the total response length. */ + rndis_response_length = UX_DEVICE_CLASS_RNDIS_NODE_ID_LENGTH; + + break; + + + default : + + /* Just return zero ULONG field. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER, 0); + + /* Set the total response length. */ + rndis_response_length = sizeof(ULONG); + + break; + + } + + /* Set the status field. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_STATUS, status); + + /* Set the buffer offset value. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER_OFFSET, + (UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER - UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_REQUEST_ID)); + + /* Store the length of the buffer. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER_LENGTH, rndis_response_length); + + /* Update the response length to add the header. */ + rndis_response_length += UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_INFO_BUFFER; + + /* Set the response length. */ + rndis -> ux_slave_class_rndis_response_length = rndis_response_length; + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_QUERY_MESSAGE_LENGTH, rndis_response_length); + + /* We are done. Return UX_SUCCESS. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_msg_reset.c b/common/usbx_device_classes/src/ux_device_class_rndis_msg_reset.c new file mode 100644 index 0000000..fbb4319 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_msg_reset.c @@ -0,0 +1,101 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_msg_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function analyzes and replies to the MSG RESET */ +/* */ +/* INPUT */ +/* */ +/* rndis Pointer to rndis class */ +/* transfer_request Pointer to the transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_long_put Put 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* RNDIS Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_rndis_msg_reset(UX_SLAVE_CLASS_RNDIS *rndis, UX_SLAVE_TRANSFER *transfer_request) +{ + +UCHAR *rndis_response; + + UX_PARAMETER_NOT_USED(transfer_request); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_MSG_RESET, rndis, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Now prepare the response. */ + rndis_response = rndis -> ux_slave_class_rndis_response; + + /* First store the command. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_CMPLT_RESET); + + /* Then the length of the response. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_MESSAGE_LENGTH, UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_RESPONSE_LENGTH); + + /* Force the status to SUCCESS. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_STATUS, UX_DEVICE_CLASS_RNDIS_STATUS_SUCCESS); + + /* Set Addressing Reset field: no need to resend multicast address list. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_ADDRESSING_RESET, 0); + + /* Set the response length. */ + rndis -> ux_slave_class_rndis_response_length = UX_DEVICE_CLASS_RNDIS_CMPLT_RESET_RESPONSE_LENGTH; + + /* We are done. Return UX_SUCCESS. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_msg_set.c b/common/usbx_device_classes/src/ux_device_class_rndis_msg_set.c new file mode 100644 index 0000000..1f5faa7 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_msg_set.c @@ -0,0 +1,135 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_msg_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function analyzes and replies to the MSG SET */ +/* */ +/* INPUT */ +/* */ +/* rndis Pointer to rndis class */ +/* transfer_request Pointer to the transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_long_get Get 32-bit value */ +/* _ux_utility_long_put Put 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* RNDIS Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_rndis_msg_set(UX_SLAVE_CLASS_RNDIS *rndis, UX_SLAVE_TRANSFER *transfer_request) +{ + +UCHAR *rndis_msg; +UCHAR *rndis_response; +ULONG rndis_oid; +ULONG status; + + /* Get the pointer to the RNDIS message. */ + rndis_msg = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Get the request ID and keep it for the response. */ + rndis -> ux_slave_class_rndis_request_id = _ux_utility_long_get(rndis_msg + UX_DEVICE_CLASS_RNDIS_MSG_SET_REQUEST_ID); + + /* Get the OID. */ + rndis_oid = _ux_utility_long_get(rndis_msg + UX_DEVICE_CLASS_RNDIS_MSG_SET_OID); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_RNDIS_MSG_SET, rndis, rndis_oid, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Now prepare the response. */ + rndis_response = rndis -> ux_slave_class_rndis_response; + + /* First store the command. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_SET_MESSAGE_TYPE, UX_DEVICE_CLASS_RNDIS_CMPLT_SET); + + /* Store the request ID. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_SET_REQUEST_ID, rndis -> ux_slave_class_rndis_request_id); + + /* By default the function will succeed. */ + status = UX_DEVICE_CLASS_RNDIS_STATUS_SUCCESS; + + /* What OID are we dealing here ? No need to treat OIDs but not sure so leave the code as is for now. */ + switch (rndis_oid) + { + + case UX_DEVICE_CLASS_RNDIS_OID_GEN_SUPPORTED_LIST : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_SUPPORTED : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_IN_USE : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_HARDWARE_STATUS : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_PHYSICAL_MEDIUM : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_LINK_SPEED : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_MEDIA_CONNECT_STATUS : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_XMIT_OK : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_OK : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_XMIT_ERROR : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_ERROR : + case UX_DEVICE_CLASS_RNDIS_OID_GEN_RCV_NO_BUFFER : + default : + break; + + } + + /* Set the status field. */ + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_SET_STATUS, status); + + /* Set the response length. */ + rndis -> ux_slave_class_rndis_response_length = UX_DEVICE_CLASS_RNDIS_CMPLT_SET_RESPONSE_LENGTH; + _ux_utility_long_put(rndis_response + UX_DEVICE_CLASS_RNDIS_CMPLT_SET_MESSAGE_LENGTH, UX_DEVICE_CLASS_RNDIS_CMPLT_SET_RESPONSE_LENGTH); + + /* We are done. Return UX_SUCCESS. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_rndis_write.c b/common/usbx_device_classes/src/ux_device_class_rndis_write.c new file mode 100644 index 0000000..a21615f --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_rndis_write.c @@ -0,0 +1,129 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device RNDIS Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_rndis.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_rndis_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a packet into a queue for later thread */ +/* processing. */ +/* */ +/* INPUT */ +/* */ +/* rndis Address of rndis class */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_mutex_on Take mutex */ +/* _ux_utility_mutex_off Free mutex */ +/* _ux_utility_event_flags_set Set event flags */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_rndis_write(VOID *rndis_class, NX_PACKET *packet) +{ + +NX_PACKET *current_packet; +NX_PACKET *next_packet; +UX_SLAVE_CLASS_RNDIS *rndis; + + /* Proper class casting. */ + rndis = (UX_SLAVE_CLASS_RNDIS *) rndis_class; + + /* Protect this thread. */ + _ux_utility_mutex_on(&rndis -> ux_slave_class_rndis_mutex); + + /* Check the queue. See if there is something that is being sent. */ + if (rndis -> ux_slave_class_rndis_xmit_queue == UX_NULL) + + /* Memorize this packet at the beginning of the queue. */ + rndis -> ux_slave_class_rndis_xmit_queue = packet; + + else + + { + + /* We get here when there is something in the queue. */ + current_packet = rndis -> ux_slave_class_rndis_xmit_queue; + + /* Get the next packet associated with the first packet. */ + next_packet = current_packet -> nx_packet_queue_next; + + /* Parse the current chain for the end. */ + while (next_packet != NX_NULL) + { + /* Remember the current packet. */ + current_packet = next_packet; + + /* See what the next packet in the chain is. */ + next_packet = current_packet -> nx_packet_queue_next; + } + + /* Memorize the packet to be sent. */ + current_packet -> nx_packet_queue_next = packet; + + } + + /* Free Mutex resource. */ + _ux_utility_mutex_off(&rndis -> ux_slave_class_rndis_mutex); + + /* The packet to be sent is the last in the chain. */ + packet -> nx_packet_queue_next = NX_NULL; + + /* Set an event to wake up the bulkin thread. */ + _ux_utility_event_flags_set(&rndis -> ux_slave_class_rndis_event_flags_group, UX_DEVICE_CLASS_RNDIS_NEW_BULKIN_EVENT, TX_OR); + + /* We are done here. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_activate.c b/common/usbx_device_classes/src/ux_device_class_storage_activate.c new file mode 100644 index 0000000..1429e09 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_activate.c @@ -0,0 +1,112 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function activates the USB storage device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to storage command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_thread_resume Resume thread */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_activate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_STORAGE *storage; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + storage = (UX_SLAVE_CLASS_STORAGE *)class -> ux_slave_class_instance; + + /* Get the interface that owns this instance. */ + interface = (UX_SLAVE_INTERFACE *) command -> ux_slave_class_command_interface; + + /* Store the class instance into the interface. */ + interface -> ux_slave_interface_class_instance = (VOID *)storage; + + /* Now the opposite, store the interface in the class instance. */ + storage -> ux_slave_class_storage_interface = interface; + + /* Resume thread. */ + status = _ux_utility_thread_resume(&class -> ux_slave_class_thread); + + /* If there is a activate function call it. */ + if (storage -> ux_slave_class_storage_instance_activate != UX_NULL) + { + /* Invoke the application. */ + storage -> ux_slave_class_storage_instance_activate(storage); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_ACTIVATE, storage, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_DEVICE_OBJECT_TYPE_INTERFACE, storage, 0, 0, 0) + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_control_request.c b/common/usbx_device_classes/src/ux_device_class_storage_control_request.c new file mode 100644 index 0000000..895e674 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_control_request.c @@ -0,0 +1,163 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_control_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function manages the based sent by the host on the control */ +/* endpoints with a CLASS or VENDOR SPECIFIC type. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_transfer_abort Abort Transfer */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_control_request(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +UX_SLAVE_CLASS *class; +ULONG request; +UX_SLAVE_CLASS_STORAGE *storage; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_ENDPOINT *endpoint_in; +UX_SLAVE_ENDPOINT *endpoint_out; + + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* Get the pointer to the transfer request associated with the control endpoint. */ + transfer_request = &device -> ux_slave_device_control_endpoint.ux_slave_endpoint_transfer_request; + + /* Extract the request type from the SETUP packet.. */ + request = *(transfer_request -> ux_slave_transfer_request_setup + UX_SETUP_REQUEST); + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the storage instance from this class container. */ + storage = (UX_SLAVE_CLASS_STORAGE *) class -> ux_slave_class_instance; + + /* Here we proceed only the standard request we know of at the device level. */ + switch (request) + { + + case UX_SLAVE_CLASS_STORAGE_RESET: + + /* We need the interface to the class. */ + interface = storage -> ux_slave_class_storage_interface; + + /* Locate the endpoints. */ + endpoint_in = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint_in -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* Wrong direction, we found the OUT endpoint first. */ + endpoint_out = endpoint_in; + + /* So the next endpoint has to be the IN endpoint. */ + endpoint_in = endpoint_out -> ux_slave_endpoint_next_endpoint; + } + else + { + + /* We found the endpoint IN first, so next endpoint is OUT. */ + endpoint_out = endpoint_in -> ux_slave_endpoint_next_endpoint; + } + + /* First cancel any transfer on the endpoint OUT, from the host. */ + transfer_request = &endpoint_out -> ux_slave_endpoint_transfer_request; + _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_APPLICATION_RESET); + + /* Then cancel any transfer on the endpoint IN, from the host. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + _ux_device_stack_transfer_abort(transfer_request, UX_TRANSFER_APPLICATION_RESET); + + /* Reset phase error. */ + storage -> ux_slave_class_storage_phase_error = UX_FALSE; + + break; + + case UX_SLAVE_CLASS_STORAGE_GET_MAX_LUN: + + /* Set the value of the number of LUN in the buffer. The max number of LUN is the + number of declared LUN - 1. */ + *transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR)(storage -> ux_slave_class_storage_number_lun -1); + + /* Set the phase of the transfer to data out. */ + transfer_request -> ux_slave_transfer_request_phase = UX_TRANSFER_PHASE_DATA_OUT; + + /* We can return the LUN number. */ + _ux_device_stack_transfer_request(transfer_request, 1, 1); + break; + + default: + + /* Unknown function. It's not handled. */ + return(UX_ERROR); + } + + /* It's handled. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_device_classes/src/ux_device_class_storage_csw_send.c b/common/usbx_device_classes/src/ux_device_class_storage_csw_send.c new file mode 100644 index 0000000..9df0fa6 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_csw_send.c @@ -0,0 +1,113 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_csw_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends the status phase of SCSI transaction. Note that */ +/* dCSWDataResidue is always set to 0 because we either transfer all */ +/* the data, or report command failure. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* status Status of CSW */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_put Put long word */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_set Set memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_csw_send(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, UCHAR csw_status) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR csw_buffer[UX_SLAVE_CLASS_STORAGE_CSW_LENGTH]; + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Ensure it is cleaned. */ + _ux_utility_memory_set(csw_buffer, 0, UX_SLAVE_CLASS_STORAGE_CSW_LENGTH); + + /* Store the signature of the CSW. */ + _ux_utility_long_put(&csw_buffer[UX_SLAVE_CLASS_STORAGE_CSW_SIGNATURE], UX_SLAVE_CLASS_STORAGE_CSW_SIGNATURE_MASK); + + /* Store the SCSI tag from the CBW. */ + _ux_utility_long_put(&csw_buffer[UX_SLAVE_CLASS_STORAGE_CSW_TAG], storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_scsi_tag); + + /* Store the status of the previous operation. */ + csw_buffer[UX_SLAVE_CLASS_STORAGE_CSW_STATUS] = csw_status; + + /* Copy the CSW into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + csw_buffer, UX_SLAVE_CLASS_STORAGE_CSW_LENGTH); + + /* We may be in a special state machine condition where the endpoint is stalled waiting for + a CLEAR_FEATURE. We will wait until the host clears the endpoint. + The transfer_request function does that. */ + /* Send the CSW back to the host. */ + status = _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_STORAGE_CSW_LENGTH, + UX_SLAVE_CLASS_STORAGE_CSW_LENGTH); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_deactivate.c b/common/usbx_device_classes/src/ux_device_class_storage_deactivate.c new file mode 100644 index 0000000..ef20dd0 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_deactivate.c @@ -0,0 +1,129 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deactivate an instance of the storage class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to a class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_all_request_abort Abort all transfers */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_deactivate(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_CLASS_STORAGE *storage; +UX_SLAVE_ENDPOINT *endpoint_in; +UX_SLAVE_ENDPOINT *endpoint_out; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + storage = (UX_SLAVE_CLASS_STORAGE *)class -> ux_slave_class_instance; + + /* We need the interface to the class. */ + interface = storage -> ux_slave_class_storage_interface; + + /* Locate the endpoints. */ + endpoint_in = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint_in -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* Wrong direction, we found the OUT endpoint first. */ + endpoint_out = endpoint_in; + + /* So the next endpoint has to be the IN endpoint. */ + endpoint_in = endpoint_out -> ux_slave_endpoint_next_endpoint; + } + else + { + + /* We found the endpoint IN first, so next endpoint is OUT. */ + endpoint_out = endpoint_in -> ux_slave_endpoint_next_endpoint; + } + + /* Terminate the transactions pending on the endpoints. */ + _ux_device_stack_transfer_all_request_abort(endpoint_in, UX_TRANSFER_BUS_RESET); + _ux_device_stack_transfer_all_request_abort(endpoint_out, UX_TRANSFER_BUS_RESET); + + /* If there is a deactivate function call it. */ + if (storage -> ux_slave_class_storage_instance_deactivate != UX_NULL) + { + + /* Invoke the application. */ + storage -> ux_slave_class_storage_instance_deactivate(storage); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_DEACTIVATE, storage, 0, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(storage); + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_entry.c b/common/usbx_device_classes/src/ux_device_class_storage_entry.c new file mode 100644 index 0000000..97cb88f --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_entry.c @@ -0,0 +1,153 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_class_device_storage_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the device storage class. It */ +/* will be called by the device stack enumeration module when the */ +/* host has sent a SET_CONFIGURATION command and the storage interface */ +/* needs to be mounted. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_initialize Initialize storage class */ +/* _ux_device_class_storage_uninitialize Uninitialize storage class */ +/* _ux_device_class_storage_activate Activate storage class */ +/* _ux_device_class_storage_deactivate Deactivate storage class */ +/* _ux_device_class_storage_control_request */ +/* Request control */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_entry(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_slave_class_command_request) + { + + case UX_SLAVE_CLASS_COMMAND_INITIALIZE: + + /* Call the init function of the Storage class. */ + status = _ux_device_class_storage_initialize(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_UNINITIALIZE: + + /* Call the init function of the Storage class. */ + status = _ux_device_class_storage_uninitialize(command); + + /* Return the completion status. */ + return(status); + + + case UX_SLAVE_CLASS_COMMAND_QUERY: + + /* Check the CLASS definition in the interface descriptor. */ + if (command -> ux_slave_class_command_class == UX_SLAVE_CLASS_STORAGE_CLASS) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_SLAVE_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the host has sent a SET_CONFIGURATION command + and this interface has to be mounted. Both Bulk endpoints have to be mounted + and the storage thread needs to be activated. */ + status = _ux_device_class_storage_activate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted. + The device endpoints have to be dismounted and the storage thread canceled. */ + status = _ux_device_class_storage_deactivate(command); + + /* Return the completion status. */ + return(status); + + case UX_SLAVE_CLASS_COMMAND_REQUEST: + + /* The request command is used when the host sends a command on the control endpoint. */ + status = _ux_device_class_storage_control_request(command); + + /* Return the completion status. */ + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_format.c b/common/usbx_device_classes/src/ux_device_class_storage_format.c new file mode 100644 index 0000000..66a83a5 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_format.c @@ -0,0 +1,102 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_format PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function formats the local media. It is not supported in this */ +/* release. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_endpoint_stall Endpoint stall */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_format(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb) +{ + + UX_PARAMETER_NOT_USED(cbwcb); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_FORMAT, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* This command is not yet supported. So Stall the endpoint. We stall the + OUT endpoint because we expect the host to send parameters. */ + _ux_device_stack_endpoint_stall(endpoint_out); + + /* Now we return a CSW with failure. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = 0x05; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x26; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x01; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return not supported error. */ + return(UX_FUNCTION_NOT_SUPPORTED); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_get_configuration.c b/common/usbx_device_classes/src/ux_device_class_storage_get_configuration.c new file mode 100644 index 0000000..8b50ab9 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_get_configuration.c @@ -0,0 +1,508 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + +#define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_PROFILE_LENGTH 228 +#define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_HEADER_LENGTH 8 +#define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_DESCRIPTOR_LENGTH 32 +#define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH 4 +#define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_LENGTH (USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_PROFILE_LENGTH - USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_DESCRIPTOR_LENGTH - USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_HEADER_LENGTH) +UCHAR usbx_device_class_storage_configuration_profile[] = { + + /* Feature Header */ + 0x00, 0x00, /* Entire length of profile filled by firmware */ + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, /* Current profile */ + + /* Feature Descriptor */ + 0x00, 0x00, /* Feature Code : profile list */ + 0x00, /* Persistent/current */ + 0x1c, /* Additional Length */ + + 0x00, 0x12, 0x00, 0x00, /* DVD-RAM */ + 0x00, 0x11, 0x00, 0x00, /* DVD-R */ + 0x00, 0x10, 0x00, 0x00, /* DVD-ROM */ + 0x00, 0x0A, 0x00, 0x00, /* CD-RW */ + 0x00, 0x09, 0x00, 0x00, /* CD-R */ + 0x00, 0x08, 0x00, 0x00, /* CD-ROM */ + 0x00, 0x02, 0x00, 0x00, /* Writable capable with removable media. */ + + + /* Feature Descriptor */ + 0x00, 0x01, /* Feature Code : core feature */ + 0x0b, /* Persistent/current */ + 0x08, /* Additional Length */ + + 0x00, 0x00, 0x00, 0x07, /* Physical Interface Standard */ + 0x01, 0x00, 0x00, 0x00, /* */ + + /* Feature Descriptor */ + 0x00, 0x02, /* Feature Code : morphing (Ability to notify initiator about + operational changes and accept initiator requests to prevent + operational changes) */ + 0x07, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x02, 0x00, 0x00, 0x00, /* Physical Interface Standard */ + + /* Feature Descriptor */ + 0x00, 0x03, /* Feature Code : Removable Medium (The medium may be removed + from the device ) */ + 0x0b, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x2b, 0x00, 0x00, 0x00, /* Physical Interface Standard */ + + /* Feature Descriptor */ + 0x00, 0x10, /* Feature Code : Random Readable (Read ability for storage devices + with random addressing) */ + 0x00, /* Persistent/current */ + 0x08, /* Additional Length */ + + 0x00, 0x00, 0x08, 0x00, /* */ + 0x00, 0x01, 0x01, 0x00, /* */ + + /* Feature Descriptor */ + 0x00, 0x1d, /* Feature Code : MultiRead (The logical unit can read all CD media types) */ + 0x00, /* Persistent/current */ + 0x00, /* Additional Length */ + + + /* Feature Descriptor */ + 0x00, 0x1e, /* Feature Code : CD Read (The ability to read CD specific structures) */ + 0x08, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x03, 0x00, 0x00, 0x00, /* */ + + /* Feature Descriptor */ + 0x00, 0x1f, /* Feature Code : DVD Read (The ability to read DVD specific structures) */ + 0x08, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x01, 0x00, 0x01, 0x00, /* */ + + /* Feature Descriptor */ + 0x00, 0x20, /* Feature Code : Random Writable (Write support for randomly addressed writes) */ + 0x04, /* Persistent/current */ + 0x0c, /* Additional Length */ + + 0x00, 0x00, 0x00, 0x00, /* */ + 0x00, 0x00, 0x08, 0x00, /* */ + 0x00, 0x00, 0x01, 0x00, /* */ + + + /* Feature Descriptor */ + 0x00, 0x21, /* Feature Code : Incremental Streaming Writable (Write support for sequential recording) */ + 0x0C, /* Persistent/current */ + 0x08, /* Additional Length */ + + 0x00, 0x00, 0x00, 0x00, /* */ + 0x00, 0x00, 0x00, 0x00, /* */ + + /* Feature Descriptor */ + 0x00, 0x23, /* Feature Code : Formattable (Support for formatting of media.) */ + 0x08, /* Persistent/current */ + 0x08, /* Additional Length */ + + 0x00, 0x00, 0x00, 0x00, /* */ + 0x00, 0x00, 0x00, 0x00, /* */ + + /* Feature Descriptor */ + 0x00, 0x24, /* Feature Code : Defect Management (Ability of the drive/media system to provide an + apparently defect-free space.) */ + 0x04, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x80, 0x00, 0x00, 0x00, /* */ + + /* Feature Descriptor */ + 0x00, 0x26, /* Feature Code : Restricted Overwrite (Write support for media that must be written + in multiples of logical blocks.) */ + 0x00, /* Persistent/current */ + 0x00, /* Additional Length */ + + + /* Feature Descriptor */ + 0x00, 0x2d, /* Feature Code : CD Track at Once (Ability to write CD with Track at Once recording) */ + 0x08, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x46, 0x00, 0x3f, 0x0f, /* */ + + /* Feature Descriptor */ + 0x00, 0x2e, /* Feature Code : CD Mastering (The ability to write CD with Session at Once or Raw write methods.) */ + 0x04, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x7f, 0x00, 0x0d, 0x00, /* */ + + /* Feature Descriptor */ + 0x00, 0x2f, /* Feature Code : DVD-R Write (The ability to write DVD specific structures) */ + 0x08, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x4e, 0x00, 0x00, 0x00, /* */ + + + 0x01, 0x00, /* Feature Code : Power Management (Initiator and device directed power management) */ + 0x07, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x00, 0x00, 0x00, 0x00, /* */ + + + 0x01, 0x01, /* Feature Code : S.M.A.R.T. (Self Monitoring Analysis and Reporting Technology (Failure prediction)) */ + 0x00, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x00, 0x00, 0x00, 0x00, /* */ + + 0x01, 0x08, /* Feature Code : Logical Unit serial number (Logical unit has a unique identifier) */ + 0x03, /* Persistent/current */ + 0x10, /* Additional Length */ + + 0x53, 0x31, 0x33, 0x36, /* Serial Number */ + 0x36, 0x59, 0x42, 0x46, + 0x37, 0x30, 0x30, 0x39, + 0x45, 0x48, 0x20, 0x20, + + 0x01, 0x0a, /* Feature Code : Not sure : says FDC STC TOC */ + 0x00, /* Persistent/current */ + 0x0c, /* Additional Length */ + + 0x46, 0x44, 0x43, 0x00, + 0x53, 0x54, 0x43, 0x00, + 0x54, 0x4F, 0x43, 0x00, + }; + + +#define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_PROFILE_LENGTH 112 +#define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_HEADER_LENGTH 8 +#define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_FEATURE_DESCRIPTOR_LENGTH 32 +#define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_FEATURE_HEADER_LENGTH 4 +#define USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_FEATURE_LENGTH (USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_PROFILE_LENGTH - USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_FEATURE_DESCRIPTOR_LENGTH - USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_HEADER_LENGTH) +UCHAR usbx_device_class_storage_configuration_active_profile[] = { + + /* Feature Header */ + 0x00, 0x00, /* Entire length of profile filled by firmware */ + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x08, /* Current profile is CD-ROM*/ + + /* Feature Descriptor */ + 0x00, 0x00, /* Feature Code : profile list */ + 0x00, /* Persistent/current */ + 0x1c, /* Additional Length */ + + 0x00, 0x12, 0x00, 0x00, /* DVD-RAM */ + 0x00, 0x11, 0x00, 0x00, /* DVD-R */ + 0x00, 0x10, 0x00, 0x00, /* DVD-ROM */ + 0x00, 0x0A, 0x00, 0x00, /* CD-RW */ + 0x00, 0x09, 0x00, 0x00, /* CD-R */ + 0x00, 0x08, 0x01, 0x00, /* CD-ROM : active profile */ + 0x00, 0x02, 0x00, 0x00, /* Writable capable with removable media. */ + + + /* Feature Descriptor */ + 0x00, 0x01, /* Feature Code : core feature */ + 0x0b, /* Persistent/current */ + 0x08, /* Additional Length */ + + 0x00, 0x00, 0x00, 0x07, /* Physical Interface Standard */ + 0x01, 0x00, 0x00, 0x00, /* */ + + /* Feature Descriptor */ + 0x00, 0x02, /* Feature Code : morphing (Ability to notify initiator about + operational changes and accept initiator requests to prevent + operational changes) */ + 0x07, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x02, 0x00, 0x00, 0x00, /* Physical Interface Standard */ + + /* Feature Descriptor */ + 0x00, 0x03, /* Feature Code : Removable Medium (The medium may be removed + from the device ) */ + 0x0b, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x2b, 0x00, 0x00, 0x00, /* Physical Interface Standard */ + + /* Feature Descriptor */ + 0x00, 0x10, /* Feature Code : Random Readable (Read ability for storage devices + with random addressing) */ + 0x01, /* Persistent/current */ + 0x08, /* Additional Length */ + + 0x00, 0x00, 0x08, 0x00, /* */ + 0x00, 0x01, 0x01, 0x00, /* */ + + /* Feature Descriptor */ + 0x00, 0x1d, /* Feature Code : MultiRead (The logical unit can read all CD media types) */ + 0x01, /* Persistent/current */ + 0x00, /* Additional Length */ + + + /* Feature Descriptor */ + 0x00, 0x1e, /* Feature Code : CD Read (The ability to read CD specific structures) */ + 0x09, /* Persistent/current */ + 0x04, /* Additional Length */ + + 0x03, 0x00, 0x00, 0x00, /* */ + + + 0x01, 0x08, /* Feature Code : Logical Unit serial number (Logical unit has a unique identifier) */ + 0x03, /* Persistent/current */ + 0x10, /* Additional Length */ + + 0x53, 0x31, 0x33, 0x36, /* Serial Number */ + 0x36, 0x59, 0x42, 0x46, + 0x37, 0x30, 0x30, 0x39, + 0x45, 0x48, 0x20, 0x20, + + }; + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_get_configuration PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a GET_CONFIGURATION command. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_utility_short_get_big_endian Get 16-bit big endian */ +/* _ux_utility_long_put_big_endian Put 32-bit big endian */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_get_configuration(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + +UINT status = 0; +UX_SLAVE_TRANSFER *transfer_request; +ULONG starting_feature; +ULONG allocation_length; +ULONG additional_length; +ULONG profile_counter; +UCHAR *profile_pointer; +ULONG feature; + + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_GET_CONFIGURATION, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Initialize the length of the configuration profile. */ + _ux_utility_long_put_big_endian(usbx_device_class_storage_configuration_profile, (USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_PROFILE_LENGTH - 4)); + + /* Initialize the length of the active configuration profile. */ + _ux_utility_long_put_big_endian(usbx_device_class_storage_configuration_active_profile, (USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_PROFILE_LENGTH - 4)); + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Get the Starting Feature. */ + starting_feature = _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_GET_CONFIGURATION_STARTING_FEATURE); + + /* Get the allocation length. */ + allocation_length = _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_GET_CONFIGURATION_ALLOCATION_LENGTH); + + /* Is the request demanding all the features ? */ + if (starting_feature == 0) + { + + /* Is the requester demanding the active profile ? */ + if ((*(cbwcb + UX_SLAVE_CLASS_STORAGE_GET_CONFIGURATION_RT) & 3) == 1) + { + + /* We get the active profile. */ + /* Can we send all the activeconfiguration profile ? If not, the host may demand the first part of the configuration to get the entire length. + In this case, return the length demanded by the host. */ + if (allocation_length >= USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_PROFILE_LENGTH) + + /* Adjust allocation length to maximum allowed. */ + allocation_length = USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_ACTIVE_PROFILE_LENGTH; + + /* Copy the CSW into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + usbx_device_class_storage_configuration_active_profile, + allocation_length); + } + else + { + + /* We get the whole profile. */ + /* Can we send all the configuration profile ? If not, the host may demand the first part of the configuration to get the entire length. + In this case, return the length demanded by the host. */ + if (allocation_length >= USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_PROFILE_LENGTH) + + /* Adjust allocation length to maximum allowed. */ + allocation_length = USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_PROFILE_LENGTH; + + /* Copy the CSW into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + usbx_device_class_storage_configuration_profile, + allocation_length); + + } + + /* Send a data payload with the configuration profile response buffer. */ + _ux_device_stack_transfer_request(transfer_request, + allocation_length, + allocation_length); + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + } + else + { + + /* The caller has demanded a specific feature. Scan our configuration profile. Jump over the beginning sections. */ + profile_pointer = usbx_device_class_storage_configuration_profile + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_HEADER_LENGTH + + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_DESCRIPTOR_LENGTH; + profile_counter = USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_LENGTH; + + /* Scan our configuration profile. */ + while (profile_counter != 0) + { + + /* Extract the feature from the configuration profile. */ + feature = _ux_utility_short_get_big_endian(profile_pointer + USBX_DEVICE_CLASS_STORAGE_FEATURE_DESCRIPTOR_FEATURE_CODE); + + /* Extract the feature length from the configuration profile. */ + additional_length = (ULONG ) *(profile_pointer + USBX_DEVICE_CLASS_STORAGE_FEATURE_DESCRIPTOR_FEATURE_ADD_LENGTH); + + /* Compare the Feature extracted with the one demanded. */ + if (feature == starting_feature) + { + + /* We found the feature, we check if the requester has enough space for us to return it. */ + if (allocation_length >= (additional_length + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_HEADER_LENGTH + + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH)) + + /* Need to adjust the allocation length. */ + allocation_length = additional_length + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_HEADER_LENGTH + + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH; + + /* Copy the CSW into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + profile_pointer, + allocation_length); + + /* Send a data payload with the read_capacity response buffer. */ + _ux_device_stack_transfer_request(transfer_request, + allocation_length, + allocation_length); + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Get out of the loop. */ + break; + } + else + { + + /* We have not yet found the feature, keep parsing. */ + if (profile_counter - additional_length - USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH <= 0) + { + + /* We are either at the end of the profile or the profile is corrupted. */ + _ux_device_stack_endpoint_stall(endpoint_in); + + /* Now we return a CSW with failure. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = UX_SLAVE_CLASS_STORAGE_SENSE_KEY_ILLEGAL_REQUEST; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x26; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x02; + + /* Set status to error. */ + status = UX_ERROR; + + /* Get out of the loop. */ + break; + + } + else + { + + /* Update the profile pointer. */ + profile_pointer += additional_length + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH; + + /* Update the length remaining to parse in profile. */ + profile_counter -= additional_length + USBX_DEVICE_CLASS_STORAGE_CONFIGURATION_FEATURE_HEADER_LENGTH; + } + } + } + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_get_performance.c b/common/usbx_device_classes/src/ux_device_class_storage_get_performance.c new file mode 100644 index 0000000..b50025b --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_get_performance.c @@ -0,0 +1,152 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + +#define USBX_DEVICE_CLASS_STORAGE_GET_PERFORMANCE_0_LENGTH 16 +UCHAR usbx_device_class_storage_performance[] = { + + 0x08, 0x00, 0x00, 0x00, 0x00, 0x23, 0x12, 0x80, + 0x00, 0x00, 0x10, 0x89, 0x00, 0x00, 0x10, 0x89 +}; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_get_performance PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a GET_PERFORMANCE SCSI command. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_utility_memory_set Set memory */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_long_put_big_endian Put 32-bit big endian */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_get_performance(UX_SLAVE_CLASS_STORAGE *storage, + ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, + UCHAR *cbwcb) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG performance_page; + + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_OTHER, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Ensure memory buffer cleaned. */ + _ux_utility_memory_set(transfer_request -> ux_slave_transfer_request_data_pointer, 0, 64); + + /* Get the performance page code. */ + performance_page = (ULONG) *(cbwcb + UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAGE); + + /* Filter it as the response depends on it. */ + switch (performance_page) + { + + case UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAGE_14 : + + /* Put the length to be returned. */ + _ux_utility_long_put_big_endian(transfer_request -> ux_slave_transfer_request_data_pointer, + UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAYLOAD_LENGTH); + + /* Put the payload to be returned. */ + _ux_utility_long_put_big_endian(transfer_request -> ux_slave_transfer_request_data_pointer + 4, + UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAYLOAD); + + /* Send a data payload with the read_capacity response buffer. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_RESPONSE_LENGTH, UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_RESPONSE_LENGTH); + break; + + case UX_SLAVE_CLASS_STORAGE_GET_PERFORMANCE_PAGE_0 : + + /* Put the length to be returned. */ + _ux_utility_long_put_big_endian(transfer_request -> ux_slave_transfer_request_data_pointer, + USBX_DEVICE_CLASS_STORAGE_GET_PERFORMANCE_0_LENGTH + 8); + + /* Copy the CSW into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer + 8, + usbx_device_class_storage_performance, USBX_DEVICE_CLASS_STORAGE_GET_PERFORMANCE_0_LENGTH); + + /* Send a data payload with the read_capacity response buffer. */ + _ux_device_stack_transfer_request(transfer_request, USBX_DEVICE_CLASS_STORAGE_GET_PERFORMANCE_0_LENGTH + 8, USBX_DEVICE_CLASS_STORAGE_GET_PERFORMANCE_0_LENGTH + 8); + break; + } + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x00; + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_get_status_notification.c b/common/usbx_device_classes/src/ux_device_class_storage_get_status_notification.c new file mode 100644 index 0000000..aaffd92 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_get_status_notification.c @@ -0,0 +1,156 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_get_status_notification PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a GET_STATUS_NOTIFICATION command. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_utility_short_put_big_endian Put 16-bit big endian */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_get_status_notification(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR *media_notification; +ULONG media_notification_length; +ULONG notification_class; + + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_READ_CAPACITY, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Ensure the callback has been initialized. */ + if (storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_notification == UX_NULL) + { + + /* We need to STALL the IN endpoint. The endpoint will be reset by the host. */ + _ux_device_stack_endpoint_stall(endpoint_in); + + /* Now we return a CSW with Error. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* Return error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } + + /* Extract the notification from the cbwcb. */ + notification_class = (ULONG) *(cbwcb + UX_SLAVE_CLASS_STORAGE_EVENT_NOTIFICATION_CLASS_REQUEST); + + /* Obtain the notification of the device. */ + status = storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_notification(storage, lun, + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_id, + notification_class, + &media_notification, + &media_notification_length); + + /* Check the status for error. */ + if (status != UX_SUCCESS) + { + + /* We need to STALL the IN endpoint. The endpoint will be reset by the host. */ + _ux_device_stack_endpoint_stall(endpoint_in); + + /* Now we return a CSW with Error. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + } + else + { + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Put the length of the notification length in the buffer. */ + _ux_utility_short_put_big_endian(transfer_request -> ux_slave_transfer_request_data_pointer, (USHORT)media_notification_length); + + /* Copy the CSW into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer + sizeof (USHORT), + media_notification, + media_notification_length); + + /* Update the notification length. */ + media_notification_length += (ULONG)sizeof (USHORT); + + /* Send a data payload with the notification buffer. */ + _ux_device_stack_transfer_request(transfer_request, + media_notification_length, + media_notification_length); + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_initialize.c b/common/usbx_device_classes/src/ux_device_class_storage_initialize.c new file mode 100644 index 0000000..db5704d --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_initialize.c @@ -0,0 +1,205 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + +/* Define the Slave Storage Class Inquiry data : DO NOT CHANGE THE LENGTH OF THESE ITEMS */ + +UCHAR _ux_system_slave_class_storage_vendor_id[] = "ExpressL"; +UCHAR _ux_system_slave_class_storage_product_id[] = "USBX storage dev"; +UCHAR _ux_system_slave_class_storage_product_rev[] = "2000"; +UCHAR _ux_system_slave_class_storage_product_serial[] = "12345678901234567890"; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB storage device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to storage command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_thread_create Create thread */ +/* _ux_utility_thread_delete Delete thread */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_initialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UINT status; +UX_SLAVE_CLASS_STORAGE *storage; +UX_SLAVE_CLASS_STORAGE_PARAMETER *storage_parameter; +UX_SLAVE_CLASS *class; +ULONG lun_index; + + /* Get the pointer to the application parameters for the storage class. */ + storage_parameter = command -> ux_slave_class_command_parameter; + + /* Ensure the number of LUN declared by the caller does not exceed the + max number allowed for LUN storage. */ + if (storage_parameter -> ux_slave_class_storage_parameter_number_lun > UX_MAX_SLAVE_LUN) + return UX_ERROR; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Create an instance of the device storage class. */ + storage = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_SLAVE_CLASS_STORAGE)); + + /* Check for successful allocation. */ + if (storage == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Allocate some memory for the thread stack. */ + class -> ux_slave_class_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* If it's OK, create thread. */ + if (class -> ux_slave_class_thread_stack != UX_NULL) + + /* This instance needs to be running in a different thread. So start + a new thread. We pass a pointer to the class to the new thread. This thread + does not start until we have a instance of the class. */ + status = _ux_utility_thread_create(&class -> ux_slave_class_thread, "ux_slave_storage_thread", + _ux_device_class_storage_thread, + (ULONG) (ALIGN_TYPE) class, (VOID *) class -> ux_slave_class_thread_stack, + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, UX_NO_TIME_SLICE, TX_DONT_START); + else + status = UX_MEMORY_INSUFFICIENT; + + /* If thread resources allocated, go on. */ + if (status == UX_SUCCESS) + { + + UX_THREAD_EXTENSION_PTR_SET(&(class -> ux_slave_class_thread), class) + + /* Store the number of LUN declared. */ + storage -> ux_slave_class_storage_number_lun = storage_parameter -> ux_slave_class_storage_parameter_number_lun; + + /* Copy each individual LUN parameters. */ + for (lun_index = 0; lun_index < storage -> ux_slave_class_storage_number_lun; lun_index++) + { + + /* Check block length size. */ + if (storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_block_length > UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE) + { + /* Cannot proceed. */ + status = (UX_MEMORY_INSUFFICIENT); + break; + } + + /* Store all the application parameter information about the media. */ + storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_last_lba = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_last_lba; + storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_block_length = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_block_length; + storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_type = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_type; + storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_removable_flag = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_removable_flag; + storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_read_only_flag = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_read_only_flag; + storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_read = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_read; + storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_flush = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_flush; + storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_write = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_write; + storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_status = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_status; + storage -> ux_slave_class_storage_lun[lun_index].ux_slave_class_storage_media_notification = storage_parameter -> ux_slave_class_storage_parameter_lun[lun_index].ux_slave_class_storage_media_notification; + } + + /* If it's OK, complete it. */ + if (status == UX_SUCCESS) + { + + /* Store the start and stop signals if needed by the application. */ + storage -> ux_slave_class_storage_instance_activate = storage_parameter -> ux_slave_class_storage_instance_activate; + storage -> ux_slave_class_storage_instance_deactivate = storage_parameter -> ux_slave_class_storage_instance_deactivate; + + /* Store the vendor id, product id, product revision and product serial. */ + if (storage_parameter -> ux_slave_class_storage_parameter_vendor_id) + storage -> ux_slave_class_storage_vendor_id = storage_parameter -> ux_slave_class_storage_parameter_vendor_id; + else + storage -> ux_slave_class_storage_vendor_id = _ux_system_slave_class_storage_vendor_id; + + if (storage_parameter -> ux_slave_class_storage_parameter_product_id) + storage -> ux_slave_class_storage_product_id = storage_parameter -> ux_slave_class_storage_parameter_product_id; + else + storage -> ux_slave_class_storage_product_id = _ux_system_slave_class_storage_product_id; + + if (storage_parameter -> ux_slave_class_storage_parameter_product_rev) + storage -> ux_slave_class_storage_product_rev = storage_parameter -> ux_slave_class_storage_parameter_product_rev; + else + storage -> ux_slave_class_storage_product_rev = _ux_system_slave_class_storage_product_rev; + + if (storage_parameter -> ux_slave_class_storage_parameter_product_serial) + storage -> ux_slave_class_storage_product_serial = storage_parameter -> ux_slave_class_storage_parameter_product_serial; + else + storage -> ux_slave_class_storage_product_serial = _ux_system_slave_class_storage_product_serial; + + /* Save the address of the STORAGE instance inside the STORAGE container. */ + class -> ux_slave_class_instance = (VOID *) storage; + + return(UX_SUCCESS); + } + + /* Free thread resources. */ + _ux_utility_thread_delete(&class -> ux_slave_class_thread); + } + + if (class -> ux_slave_class_thread_stack != UX_NULL) + _ux_utility_memory_free(&class -> ux_slave_class_thread_stack); + + /* Free instance. */ + _ux_utility_memory_free(storage); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_inquiry.c b/common/usbx_device_classes/src/ux_device_class_storage_inquiry.c new file mode 100644 index 0000000..aa77c82 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_inquiry.c @@ -0,0 +1,207 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_inquiry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a INQUIRY command. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_set Set memory */ +/* _ux_utility_short_put_big_endian Put 16-bit big endian */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_inquiry(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR inquiry_page_code; +UCHAR inquiry_length; +UCHAR inquiry_buffer[UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH]; + + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_INQUIRY, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* From the SCSI Inquiry payload, get the page code. */ + inquiry_page_code = *(cbwcb + UX_SLAVE_CLASS_STORAGE_INQUIRY_PAGE_CODE); + + /* And the length to be returned. */ + inquiry_length = *(cbwcb + UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_ADDITIONAL_LENGTH); + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Ensure the data buffer is cleaned. */ + _ux_utility_memory_set(inquiry_buffer, 0, UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH); + + /* Check for the maximum length to be returned. */ + if (inquiry_length > UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH) + inquiry_length = UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH; + + /* Ensure we know about the page code. */ + switch (inquiry_page_code) + { + + case UX_SLAVE_CLASS_STORAGE_INQUIRY_PAGE_CODE_STANDARD: + + /* Store the product type. */ + inquiry_buffer[UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_PERIPHERAL_TYPE] = (UCHAR)storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_type; + + /* Store the Media Removable bit. */ + inquiry_buffer[UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_REMOVABLE_MEDIA] = (UCHAR)storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_removable_flag; + + /* Store the Data Format bit. */ + if (storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_type == UX_SLAVE_CLASS_STORAGE_MEDIA_CDROM) + inquiry_buffer[UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_DATA_FORMAT] = 0x32; + else + inquiry_buffer[UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_DATA_FORMAT] = 0x00; + + /* Store the length of the response. There is a hack here. For CD-ROM, the data lg is fixed to 0x5B ! */ + if (storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_type != UX_SLAVE_CLASS_STORAGE_MEDIA_CDROM) + inquiry_buffer[UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_ADDITIONAL_LENGTH] = UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH; + else + inquiry_buffer[UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_ADDITIONAL_LENGTH] = UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH_CD_ROM; + + /* Fill in the storage vendor ID. */ + _ux_utility_memory_copy(inquiry_buffer + UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_VENDOR_INFORMATION, + storage -> ux_slave_class_storage_vendor_id, 8); + + /* Fill in the product vendor ID. */ + _ux_utility_memory_copy(inquiry_buffer + UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_PRODUCT_ID, + storage -> ux_slave_class_storage_product_id, 16); + + /* Fill in the product revision number. */ + _ux_utility_memory_copy(inquiry_buffer + UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_PRODUCT_REVISION, + storage -> ux_slave_class_storage_product_rev, 4); + + /* Copy the Inquiry Buffer into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, inquiry_buffer, inquiry_length); + + /* Send a data payload with the inquiry response buffer. */ + _ux_device_stack_transfer_request(transfer_request, inquiry_length, inquiry_length); + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x00; + + break; + + case UX_SLAVE_CLASS_STORAGE_INQUIRY_PAGE_CODE_SERIAL: + + /* Initialize the page code in response buffer. */ + _ux_utility_short_put_big_endian(transfer_request -> ux_slave_transfer_request_data_pointer, UX_SLAVE_CLASS_STORAGE_INQUIRY_PAGE_CODE_SERIAL); + + /* Initialize the length of the serial number in response buffer. */ + _ux_utility_short_put_big_endian(transfer_request -> ux_slave_transfer_request_data_pointer + 2, 20); + + /* Copy the serial number buffer into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer + 4, storage -> ux_slave_class_storage_product_serial, 20); + + /* Send a data payload with the inquiry response buffer. */ + _ux_device_stack_transfer_request(transfer_request, 24, 24); + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x00; + + break; + + default: + + /* The page code is not supported. */ + _ux_device_stack_endpoint_stall(endpoint_in); + + /* Now we return a CSW with failure. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = 0x05; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x26; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x01; + + /* Return error. */ + status = UX_ERROR; + + break; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_mode_select.c b/common/usbx_device_classes/src/ux_device_class_storage_mode_select.c new file mode 100644 index 0000000..f314a52 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_mode_select.c @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_mode_select PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a MODE_SELECT SCSI command. It is not */ +/* supported in this release. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_mode_select(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + + UX_PARAMETER_NOT_USED(cbwcb); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_MODE_SELECT, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* This command is not yet supported. So Stall the endpoint. */ + _ux_device_stack_endpoint_stall(endpoint_out); + + /* Now we return a CSW with failure. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = 0x05; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x26; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x01; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return not supported error! */ + return(UX_FUNCTION_NOT_SUPPORTED); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_mode_sense.c b/common/usbx_device_classes/src/ux_device_class_storage_mode_sense.c new file mode 100644 index 0000000..53934c5 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_mode_sense.c @@ -0,0 +1,261 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + +#ifdef UX_SLAVE_CLASS_STORAGE_INCLUDE_MMC +#define USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_CDROM_LENGTH (0x42 + 2) +UCHAR usbx_device_class_storage_mode_sense_page_cdrom[USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_CDROM_LENGTH] = { + + 0x2A, 0x42, 0x3F, 0x37, 0xF1, 0x77, 0x29, 0x23, + 0x10, 0x89, 0x01, 0x00, 0x02, 0x00, 0x05, 0x84, + 0x00, 0x10, 0x10, 0x89, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + +}; +#else +#define USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_CDROM_LENGTH (0) +#endif +#define USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_CACHE_LENGTH (0x12 + 2) +#define USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_IEC_LENGTH (0x0A + 2) + +/* Ensure sense pages can fit in the bulk in endpoint's transfer buffer. */ +#define USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_ALL_RESPONSE_LENGTH ( \ + UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_HEADER_LENGTH_10 + \ + USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_CDROM_LENGTH + \ + USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_CACHE_LENGTH + \ + USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_IEC_LENGTH) +#if USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_ALL_RESPONSE_LENGTH > UX_SLAVE_REQUEST_DATA_MAX_LENGTH +#error "The maximum-sized MODE_SENSE response cannot fit inside the bulk in endpoint's data buffer." +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_mode_sense PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a MODE_SENSE SCSI command. It supports */ +/* the standard page for the CD-ROM. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_utility_short_get_big_endian Get 16-bit big endian */ +/* _ux_utility_short_put_big_endian Put 16-bit big endian */ +/* _ux_utility_memory_set Set memory */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_mode_sense(UX_SLAVE_CLASS_STORAGE *storage, + ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, + UCHAR *cbwcb) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG mode_sense_reply_length; +ULONG page_code; +ULONG mode_sense_command; +UCHAR read_only_flag; +ULONG response_header_length; +ULONG medium_type_index; +ULONG mode_data_length; +UCHAR *page_pointer; +ULONG page_length; + + + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_MODE_SENSE, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Get the command format : we have 1a and 5a. */ + mode_sense_command = (ULONG) *(cbwcb + UX_SLAVE_CLASS_STORAGE_MODE_SENSE_OPERATION); + + /* Extract the notification from the cbwcb. */ + page_code = (ULONG) *(cbwcb + UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PC_PAGE_CODE); + + /* Check the command. */ + if (mode_sense_command == UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT) + { + + /* Extract the length to be returned by the cbwcb. */ + mode_sense_reply_length = (ULONG) *(cbwcb + UX_SLAVE_CLASS_STORAGE_MODE_SENSE_ALLOCATION_LENGTH_6); + medium_type_index = UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_MEDIUM_TYPE_6; + response_header_length = UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_HEADER_LENGTH_6; + } + + else + { + + /* Extract the length to be returned by the cbwcb. */ + mode_sense_reply_length = _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_MODE_SENSE_ALLOCATION_LENGTH_10); + medium_type_index = UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_MEDIUM_TYPE_10; + response_header_length = UX_SLAVE_CLASS_STORAGE_MODE_SENSE_PARAMETER_HEADER_LENGTH_10; + } + + /* Ensure reply not exceed storage buffer. */ + if (mode_sense_reply_length > UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE) + mode_sense_reply_length = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE; + + /* Ensure memory buffer cleaned. */ + _ux_utility_memory_set(transfer_request -> ux_slave_transfer_request_data_pointer, 0, mode_sense_reply_length); + + /* Establish READ ONLY flag. */ + if (storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_read_only_flag == UX_TRUE) + + /* This device is Read Only. */ + read_only_flag = 0x80; + + else + + /* This device can be written to. */ + read_only_flag = 0; + + /* Build response based on expected page codes. */ + + /* Initialize length and page pointer. */ + mode_data_length = response_header_length; + page_pointer = transfer_request -> ux_slave_transfer_request_data_pointer + response_header_length; + +#ifdef UX_SLAVE_CLASS_STORAGE_INCLUDE_MMC + /* CD Capabilities and Mechanical Status mode page. */ + if(page_code == UX_SLAVE_CLASS_STORAGE_MMC2_PAGE_CODE_CDROM || + page_code == UX_SLAVE_CLASS_STORAGE_PAGE_CODE_ALL) + { + page_length = USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_CDROM_LENGTH; + + /* Copy page data. */ + _ux_utility_memory_copy(page_pointer, usbx_device_class_storage_mode_sense_page_cdrom, page_length); + + /* Update pointer and length. */ + mode_data_length += page_length; + page_pointer += page_length; + } +#endif + + /* Caching mode page is returned if cache flush callback implemented. */ + if (storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_flush != UX_NULL && + (page_code == UX_SLAVE_CLASS_STORAGE_PAGE_CODE_CACHE || + page_code == UX_SLAVE_CLASS_STORAGE_PAGE_CODE_ALL)) + { + page_length = USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_CACHE_LENGTH; + + /* Store page code. */ + *(page_pointer) = UX_SLAVE_CLASS_STORAGE_PAGE_CODE_CACHE; + + /* Store the length of the page data. */ + *(page_pointer + 1) = 0x12; + + /* Set the Write Cache Enabled (WCE) bit. */ + *(page_pointer + 2) |= 0x04; + + mode_data_length += page_length; + page_pointer += page_length; + } + + /* Informational Exceptions Control mode page. */ + if (page_code == UX_SLAVE_CLASS_STORAGE_PAGE_CODE_IEC || + page_code == UX_SLAVE_CLASS_STORAGE_PAGE_CODE_ALL) + { + page_length = USBX_DEVICE_CLASS_STORAGE_MODE_SENSE_PAGE_IEC_LENGTH; + + /* Store page code. */ + *(page_pointer) = UX_SLAVE_CLASS_STORAGE_PAGE_CODE_IEC; + + /* Store the length of the page data. */ + *(page_pointer + 1) = 0x0A; + + mode_data_length += page_length; + page_pointer += page_length; + } + + /* Put the payload length in the header. */ + if (mode_sense_command == UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT) + * transfer_request -> ux_slave_transfer_request_data_pointer = (UCHAR)(mode_data_length); + else + _ux_utility_short_put_big_endian(transfer_request -> ux_slave_transfer_request_data_pointer, (USHORT)mode_data_length); + + /* Store the write protection flag. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + medium_type_index + 1) = read_only_flag; + + /* Send a payload with the response buffer. */ + _ux_device_stack_transfer_request(transfer_request, mode_sense_reply_length, mode_sense_reply_length); + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x00; + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_prevent_allow_media_removal.c b/common/usbx_device_classes/src/ux_device_class_storage_prevent_allow_media_removal.c new file mode 100644 index 0000000..903922e --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_prevent_allow_media_removal.c @@ -0,0 +1,96 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_prevent_allow_media_removal PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allows or prevents the removal of the media. We don't */ +/* do anything here, just the CSW is returned with a SUCCESS code. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_prevent_allow_media_removal(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + + UX_PARAMETER_NOT_USED(cbwcb); + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_PREVENT_ALLOW_MEDIA_REMOVAL, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* We return a CSW with success. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x00; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read.c b/common/usbx_device_classes/src/ux_device_class_storage_read.c new file mode 100644 index 0000000..4fb48dd --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_read.c @@ -0,0 +1,226 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a READ command in 32 or 16 bits. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* scsi_command SCSI command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_class_storage_media_read) Read from media */ +/* (ux_slave_class_storage_media_status) Get media status */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_get_big_endian Get 32-bit big endian */ +/* _ux_utility_short_get_big_endian Get 16-bit big endian */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_read(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb, UCHAR scsi_command) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG lba; +ULONG total_number_blocks; +ULONG number_blocks; +ULONG media_status; +ULONG total_length; +ULONG transfer_length; + + UX_PARAMETER_NOT_USED(endpoint_out); + + /* Get the LBA from the CBWCB. */ + lba = _ux_utility_long_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_READ_LBA); + + /* The type of commands will tell us the width of the field containing the number + of sectors to read. */ + if (scsi_command == UX_SLAVE_CLASS_STORAGE_SCSI_READ16) + + /* Get the number of blocks from the CBWCB in 16 bits. */ + total_number_blocks = _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_READ_TRANSFER_LENGTH_16); + + else + + /* Get the number of blocks from the CBWCB in 32 bits. */ + total_number_blocks = _ux_utility_long_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_READ_TRANSFER_LENGTH_32); + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Compute the total length to transfer and how much remains. */ + total_length = total_number_blocks * storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_block_length; + + /* It may take several transfers to send the requested data. */ + while (total_number_blocks) + { + + /* Obtain the status of the device. */ + status = storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_status(storage, lun, + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_id, &media_status); + + /* Update the request sense. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = (UCHAR) (media_status & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = (UCHAR) ((media_status >> 8 ) & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = (UCHAR) ((media_status >> 16 ) & 0xff); + + /* If there is a problem, return a failed command. */ + if (status != UX_SUCCESS) + { + + /* We have a problem, media status error. Return a bad completion and wait for the + REQUEST_SENSE command. */ + _ux_device_stack_endpoint_stall(endpoint_in); + + /* Now we return a CSW with failure. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* Return an error. */ + return(UX_ERROR); + } + + /* How much can we send in this transfer? */ + if (total_length > UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE) + + /* Compute the transfer length based on the maximum allowed. */ + transfer_length = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE; + + else + + /* Compute the transfer length based on what is left to transfer. */ + transfer_length = total_length; + + /* Compute the number of blocks to transfer. */ + number_blocks = transfer_length / storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_block_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_READ, storage, lun, transfer_request -> ux_slave_transfer_request_data_pointer, + number_blocks, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Execute the read command from the local media. */ + status = storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_read(storage, lun, + transfer_request -> ux_slave_transfer_request_data_pointer, number_blocks, lba, &media_status); + + /* If there is a problem, return a failed command. */ + if (status != UX_SUCCESS) + { + + /* We have a problem, request error. Return a bad completion and wait for the + REQUEST_SENSE command. */ + _ux_device_stack_endpoint_stall(endpoint_in); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = (UCHAR) (media_status & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = (UCHAR) ((media_status >> 8 ) & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = (UCHAR) ((media_status >> 16 ) & 0xff); + + /* Now we return a CSW with failure. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* Return an error. */ + return(UX_ERROR); + } + + /* Sends the data payload back to the caller. */ + status = _ux_device_stack_transfer_request(transfer_request, transfer_length, transfer_length); + + /* Check the status. */ + if(status != UX_SUCCESS) + { + + /* We have a problem, request error. Return a bad completion and wait for the + REQUEST_SENSE command. */ + _ux_device_stack_endpoint_stall(endpoint_in); + + /* Update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = 0x02; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x54; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x00; + + /* Now we return a CSW with failure. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* Return an error. */ + return(UX_ERROR); + + } + + /* Update the LBA address. */ + lba += number_blocks; + + /* Update the length to remain. */ + total_length -= transfer_length; + + /* Update the number of blocks to read. */ + total_number_blocks -= number_blocks; + } + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Return completion status. */ + return(status); +} diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read_capacity.c b/common/usbx_device_classes/src/ux_device_class_storage_read_capacity.c new file mode 100644 index 0000000..cd3a63a --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_read_capacity.c @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_read_capacity PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a READ_CAPACITY command. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_utility_long_put_big_endian Put 32-bit big endian */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_set Set memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_read_capacity(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + +UINT status; +ULONG media_status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR read_capacity_buffer[UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH]; + + UX_PARAMETER_NOT_USED(cbwcb); + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_READ_CAPACITY, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the status of the device. */ + status = storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_status(storage, lun, + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_id, &media_status); + + /* Update the request sense. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = (UCHAR) (media_status & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = (UCHAR) ((media_status >> 8 ) & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = (UCHAR) ((media_status >> 16 ) & 0xff); + + /* Check the status for error. */ + if (status != UX_SUCCESS) + { + + /* We need to STALL the IN endpoint. The endpoint will be reset by the host. */ + _ux_device_stack_endpoint_stall(endpoint_in); + + /* Now we return a CSW with Error. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + } + else + { + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Ensure it is cleaned. */ + _ux_utility_memory_set(read_capacity_buffer, 0, UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH); + + /* Insert the last LBA address in the response. */ + _ux_utility_long_put_big_endian(&read_capacity_buffer[UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LAST_LBA], + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_last_lba); + + /* Insert the block length in the response. */ + _ux_utility_long_put_big_endian(&read_capacity_buffer[UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_BLOCK_SIZE], + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_block_length); + + /* Copy the CSW into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + read_capacity_buffer, UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH); + + /* Send a data payload with the read_capacity response buffer. */ + _ux_device_stack_transfer_request(transfer_request, + UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH, + UX_SLAVE_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH); + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read_disk_information.c b/common/usbx_device_classes/src/ux_device_class_storage_read_disk_information.c new file mode 100644 index 0000000..ad52508 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_read_disk_information.c @@ -0,0 +1,159 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + +#define USBX_DEVICE_CLASS_STORAGE_DISK_INFORMATION_LENGTH 34 +UCHAR usbx_device_class_storage_disk_information[] = { + + 0x00, 0x00, /* Entire length of disk_information */ + 0x0e, /* Erasable/state of last session/disk status ...*/ + 0x01, /* Number of first track on disk. */ + 0x01, /* Number of sessions. */ + 0x01, /* First track number in last session. */ + 0x01, /* Last track number in last session. */ + + 0x00, /* DID_V, DBC_V, URU .... */ + 0x00, /* Disk type */ + 0x00, /* Number of sessions */ + 0x00, /* First Track Number in last session */ + 0x00, /* Last Track Number in last session */ + + 0x00, 0x00, 0x00, 0x00, /* Disk Identification */ + 0xff, 0xff, 0xff, 0xff, /* Last session lead in start time */ + 0xff, 0xff, 0xff, 0xff, /* Last possible start time for SOLO */ + 0x00, 0x00, 0x00, 0x00, /* Disk Bar Code */ + 0x00, /* Reserved */ + 0x00, /* Number of OPC table entries. */ + 0x00, 0x00, 0x00, 0x00, /* Some padding ? */ + 0x00, 0x00 /* */ + + }; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_read_disk_information PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a READ_DISK_INFORMATION command. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_short_put_big_endian Put 16-bit big endian */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_read_disk_information(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG allocation_length; + + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_GET_CONFIGURATION, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Initialize the length of the disk information field. */ + _ux_utility_short_put_big_endian(usbx_device_class_storage_disk_information, (USBX_DEVICE_CLASS_STORAGE_DISK_INFORMATION_LENGTH - 2)); + + /* Clean the disk status. */ + usbx_device_class_storage_disk_information[2] &= (UCHAR)~3; + + /* Update the disk status. */ + usbx_device_class_storage_disk_information[2] = (UCHAR)(usbx_device_class_storage_disk_information[2] | (storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_disk_status & 3)); + + /* Clean the last session state. */ + usbx_device_class_storage_disk_information[2] &= (UCHAR)~0x0c; + + /* Update the last session state. */ + usbx_device_class_storage_disk_information[2] = (UCHAR)(usbx_device_class_storage_disk_information[2] | ((storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_last_session_state << 2) & 0x0c)); + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Get the allocation length. */ + allocation_length = _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_READ_DISK_INFORMATION_ALLOCATION_LENGTH); + + /* Can we send all the disk information ? */ + if (allocation_length > USBX_DEVICE_CLASS_STORAGE_DISK_INFORMATION_LENGTH) + + /* Yes, so send only the disk information profile. */ + allocation_length = USBX_DEVICE_CLASS_STORAGE_DISK_INFORMATION_LENGTH; + + /* Copy the CSW into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + usbx_device_class_storage_disk_information, + allocation_length); + + /* Send a data payload with the read_capacity response buffer. */ + _ux_device_stack_transfer_request(transfer_request, + allocation_length, + allocation_length); + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read_dvd_structure.c b/common/usbx_device_classes/src/ux_device_class_storage_read_dvd_structure.c new file mode 100644 index 0000000..5375fd0 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_read_dvd_structure.c @@ -0,0 +1,276 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + +#define USBX_DEVICE_CLASS_STORAGE_DVD_STRUCTURE_LENGTH (2048 + 4) +UCHAR usbx_device_class_storage_dvd_structure[] = { + 0x08, 0x02, 0x00, 0x00, 0x25, 0x0F, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0xAF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x00, 0x04, 0x6E, 0xA0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x66, 0x78, 0x80, 0x00, 0x03, 0x54, 0x59, 0x47, 0x30, 0x32, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x05, 0xAA, 0xA0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x08, 0x01, 0x11, + 0x87, 0x78, 0x80, 0x00, 0x07, 0x88, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x06, 0x13, 0x0D, + 0x10, 0x0E, 0x07, 0x00, 0x09, 0x97, 0x07, 0x0D, 0x0B, 0x78, 0x88, 0x00, 0x0A, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x0B, 0x06, 0x18, 0x17, 0x85, 0x78, 0x75, 0x00, 0x0C, 0xD6, 0x89, 0xA8, + 0x92, 0x01, 0x20, 0x00, 0x0D, 0x10, 0x00, 0xD0, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x09, 0x21, 0x35, + 0x2D, 0x29, 0x1B, 0x00, 0x0F, 0x50, 0x1B, 0x2B, 0x1D, 0x97, 0xB5, 0x00, 0x10, 0x88, 0x84, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x09, 0x2D, 0x35, + 0x2D, 0x2B, 0x1A, 0x00, 0x13, 0x50, 0x1D, 0x2B, 0x1F, 0x97, 0xB5, 0x00, 0x14, 0x88, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 + + }; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_read_dvd_structure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a READ_DVD_STRUCTURE command. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_short_get_big_endian Get 16-bit big endian */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_read_dvd_structure(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG allocation_length; +ULONG transfer_length = 0; +UCHAR *dvd_structure_pointer; + + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_OTHER, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Get the allocation length. */ + allocation_length = _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_READ_DISK_INFORMATION_ALLOCATION_LENGTH); + + /* Can we send all the disk information ? */ + if (allocation_length > USBX_DEVICE_CLASS_STORAGE_DVD_STRUCTURE_LENGTH) + + /* Yes, so send only the disk information profile. */ + allocation_length = USBX_DEVICE_CLASS_STORAGE_DVD_STRUCTURE_LENGTH; + + /* Set dvd structure pointer. */ + dvd_structure_pointer = usbx_device_class_storage_dvd_structure; + + /* Send back everything in chunks. */ + while (allocation_length) + { + + /* Check length. Is it more than one packet ? */ + if (allocation_length > UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE) + + /* Compute the transfer length based on the maximum allowed. */ + transfer_length = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE; + + else + + /* Compute the transfer length based on what is left to transfer. */ + transfer_length = allocation_length; + + /* Copy the CSW into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + dvd_structure_pointer, + transfer_length); + + /* Send a data payload with the read_capacity response buffer. */ + status = _ux_device_stack_transfer_request(transfer_request, + transfer_length, + transfer_length); + + /* Check transfer completion status. */ + if (status != UX_SUCCESS) + return(status); + + /* Advance pointer to dvd structure. */ + dvd_structure_pointer += transfer_length; + + /* Subtract what is left to send out. */ + allocation_length -= transfer_length; + } + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read_format_capacity.c b/common/usbx_device_classes/src/ux_device_class_storage_read_format_capacity.c new file mode 100644 index 0000000..3be024e --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_read_format_capacity.c @@ -0,0 +1,127 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_read_format_capacity PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a READ_FORMAT_CAPACITY command. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_memory_set Set memory */ +/* _ux_utility_long_put_big_endian Put 32-bit big endian */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_read_format_capacity(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR read_format_capacity_buffer[UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LENGTH]; + + UX_PARAMETER_NOT_USED(cbwcb); + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_READ_FORMAT_CAPACITY, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Ensure it is cleaned. */ + _ux_utility_memory_set(read_format_capacity_buffer, 0, UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LENGTH); + + /* Insert the size of the response block. */ + _ux_utility_long_put_big_endian(&read_format_capacity_buffer[UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_SIZE], 8); + + /* Insert the last LBA address in the response. */ + _ux_utility_long_put_big_endian(&read_format_capacity_buffer[UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LAST_LBA], + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_last_lba); + + /* Insert the block length in the response. This is in 3 bytes. */ + _ux_utility_long_put_big_endian(&read_format_capacity_buffer[UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_BLOCK_SIZE], + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_block_length); + + /* Insert the response code : always 2. */ + read_format_capacity_buffer[UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_DESC_CODE] = 2; + + /* Copy the CSW into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + read_format_capacity_buffer, UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LENGTH); + + /* Send a data payload with the read_capacity response buffer. */ + _ux_device_stack_transfer_request(transfer_request, + UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LENGTH, + UX_SLAVE_CLASS_STORAGE_READ_FORMAT_CAPACITY_RESPONSE_LENGTH); + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_read_toc.c b/common/usbx_device_classes/src/ux_device_class_storage_read_toc.c new file mode 100644 index 0000000..515adfe --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_read_toc.c @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_read_toc PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a READ_TOC SCSI command. This is only for */ +/* supporting CD-ROM emulation and is hardwired to what Windows wants. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_utility_memory_set Set memory */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_short_get_big_endian Get 16-bit big endian */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_read_toc(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG allocation_length; +ULONG toc_length; +UCHAR toc_buffer[20]; + + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_READ_TOC, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Reset this buffer. */ + _ux_utility_memory_set(toc_buffer,0,20); + + /* Get the allocation length. */ + allocation_length = _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_READ_TOC_ALLOCATION_LENGTH); + + /* Insert the fist and last tack number. */ + toc_buffer[2] = 0x01; + toc_buffer[3] = 0x01; + + /* Set TOC length by default. */ + toc_length = 20; + + /* Insert the ADR and control values. */ + toc_buffer[5] = 0x14; + + /* Insert the TOC tack number. */ + toc_buffer[6] = 0x01; + + /* Check if the request is for the TOC or time stamp. */ + switch (*(cbwcb + UX_SLAVE_CLASS_STORAGE_READ_TOC_FORMAT)) + { + + case 0x02 : + + /* Set the toc buffer length. */ + toc_length = 20; + + /* Insert the TOC buffer length. */ + toc_buffer[1] = 0x12; + + /* Insert some time values. */ + toc_buffer[10] = 0x02; + toc_buffer[13] = 0x17; + toc_buffer[14] = 0xAA; + toc_buffer[18] = 0x04; + toc_buffer[19] = 0x1a; + + break; + + case 0x01 : + + /* Set the toc buffer length. */ + toc_length = 19; + + /* Insert the TOC buffer length. */ + toc_buffer[1] = 0x12; + + toc_buffer[13] = 0x17; + toc_buffer[14] = 0xAA; + toc_buffer[19] = 0xb0; + + break; + + case 0x00 : + + /* Set the toc buffer length. */ + toc_length = 20; + + /* Insert the TOC buffer length. */ + toc_buffer[1] = 0x12; + + /* Insert some time values. */ + toc_buffer[10] = 0x02; + toc_buffer[13] = 0x17; + toc_buffer[14] = 0xAA; + toc_buffer[18] = 0x04; + toc_buffer[19] = 0x1a; + + break; + } + + /* Copy the TOC Buffer into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, toc_buffer, toc_length); + + /* Check how much we can send back. */ + if (allocation_length > toc_length) + + /* We return less than demanded. */ + allocation_length = toc_length; + + /* Send a data payload with the TOC response buffer. */ + _ux_device_stack_transfer_request(transfer_request, allocation_length, allocation_length); + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Return completion status. */ + return(status); + +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_report_key.c b/common/usbx_device_classes/src/ux_device_class_storage_report_key.c new file mode 100644 index 0000000..4deb505 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_report_key.c @@ -0,0 +1,153 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_report_key PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a REPORT_KEY SCSI command. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_utility_memory_set Set memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_report_key(UX_SLAVE_CLASS_STORAGE *storage, + ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, + UCHAR *cbwcb) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG allocation_length; +ULONG key_format; + + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_OTHER, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Get the report key. */ + key_format = (ULONG) *(cbwcb + UX_SLAVE_CLASS_STORAGE_REPORT_KEY_FORMAT); + + /* Extract the length to be returned by the cbwcb. */ + allocation_length = _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ALLOCATION_LENGTH); + + /* Ensure memory buffer cleaned. */ + _ux_utility_memory_set(transfer_request -> ux_slave_transfer_request_data_pointer, 0, 64); + + /* Filter page code. This is necessary to isolate the CD-ROM mode sense response. */ + switch (key_format) + { + + case UX_SLAVE_CLASS_STORAGE_REPORT_KEY_FORMAT_RPC : + + + /* Put the length to be returned. */ + _ux_utility_short_put_big_endian(transfer_request -> ux_slave_transfer_request_data_pointer, + UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_PAYLOAD); + + /* Put the reset field. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_RESET_FIELD) = 0x25; + + /* Put the region mask. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_REGION_MASK) = 0xFF; + + /* No region code. */ + *(transfer_request -> ux_slave_transfer_request_data_pointer + UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_RPC_SCHEME) = 0x00; + + /* Compute the payload to return. Depends on the request. */ + if (allocation_length > UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_LENGTH) + + /* Adjust the reply. */ + allocation_length = UX_SLAVE_CLASS_STORAGE_REPORT_KEY_ANSWER_LENGTH; + + /* Send a data payload with the read_capacity response buffer. */ + _ux_device_stack_transfer_request(transfer_request, allocation_length, allocation_length); + + break; + + default : + + /* Send a data payload with the read_capacity response buffer. */ + status = _ux_device_stack_transfer_request(transfer_request, 0, 0); + break; + + } + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x00; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x00; + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_request_sense.c b/common/usbx_device_classes/src/ux_device_class_storage_request_sense.c new file mode 100644 index 0000000..8601187 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_request_sense.c @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_request_sense PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a request sense command. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_set Set memory */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_request_sense(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +UCHAR sense_buffer[UX_SLAVE_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH]; + + UX_PARAMETER_NOT_USED(cbwcb); + UX_PARAMETER_NOT_USED(endpoint_out); + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_in -> ux_slave_endpoint_transfer_request; + + /* Ensure it is cleaned. */ + _ux_utility_memory_set(sense_buffer, 0, UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH); + + /* Initialize the response buffer with the error code. */ + sense_buffer[UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ERROR_CODE] = + UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ERROR_CODE_VALUE; + + /* Initialize the response buffer with the sense key. */ + sense_buffer[UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_SENSE_KEY] = + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key; + + /* Initialize the response buffer with the code. */ + sense_buffer[UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE] = + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code; + + /* Initialize the response buffer with the code qualifier. */ + sense_buffer[UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE_QUALIFIER] = + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_REQUEST_SENSE, storage, lun, + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key, + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Initialize the response buffer with the additional length. */ + sense_buffer[UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ADD_LENGTH] = 10; + + + /* Copy the request sense response into the transfer request memory. */ + _ux_utility_memory_copy(transfer_request -> ux_slave_transfer_request_data_pointer, + sense_buffer, UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH); + + /* Send a data payload with the sense codes. */ + _ux_device_stack_transfer_request(transfer_request, UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH, + UX_SLAVE_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH); + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_start_stop.c b/common/usbx_device_classes/src/ux_device_class_storage_start_stop.c new file mode 100644 index 0000000..2bd9f12 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_start_stop.c @@ -0,0 +1,91 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_start_stop PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts or stops the media. This command will not do */ +/* anything here, just the CSW is returned with a SUCCESS code. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_start_stop(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + + UX_PARAMETER_NOT_USED(cbwcb); + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_START_STOP, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* We return a CSW with success. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_synchronize_cache.c b/common/usbx_device_classes/src/ux_device_class_storage_synchronize_cache.c new file mode 100644 index 0000000..bff1623 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_synchronize_cache.c @@ -0,0 +1,174 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_synchronize_cache PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a SYNCHRONIZE_CACHE command in 32 or 16 */ +/* bits. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to the CBWCB */ +/* scsi_command SCSI command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_class_storage_media_status) Get media status */ +/* (ux_slave_class_storage_media_flush) Flush media */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_utility_long_get_big_endian Get 32-bit big endian */ +/* _ux_utility_short_get_big_endian Get 16-bit big endian */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_synchronize_cache(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR *cbwcb, UCHAR scsi_command) +{ + +UINT status; +ULONG lba; +USHORT number_blocks; +ULONG media_status; +UCHAR flags; + + + UX_PARAMETER_NOT_USED(endpoint_out); + UX_PARAMETER_NOT_USED(scsi_command); + + /* Is there not an implementation? */ + if (storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_flush == UX_NULL) + { + + /* This means the application is not using a cache. */ + + /* Return a CSW with success. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Return success. */ + return(UX_SUCCESS); + } + + flags = *(cbwcb + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS); + + /* Get the LBA and number of blocks from the CBWCB in 16 bits. */ + lba = _ux_utility_long_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_LBA); + number_blocks = (USHORT)_ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_NUMBER_OF_BLOCKS); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_SYNCHRONIZE_CACHE, storage, lun, lba, number_blocks, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the status of the device. */ + status = storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_status(storage, + lun, storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_id, &media_status); + + /* Update the request sense. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = (UCHAR) (media_status & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = (UCHAR) ((media_status >> 8 ) & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = (UCHAR) ((media_status >> 16 ) & 0xff); + + /* If there is a problem, return a failed command. */ + if (status != UX_SUCCESS) + { + + /* We have a problem, media status error. Return a bad completion and wait for the + REQUEST_SENSE command. */ + _ux_device_stack_endpoint_stall(endpoint_in); + + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* We are done here. */ + return(UX_ERROR); + } + + /* If the immediate bit is set, we return a CSW before flush. */ + else if ((flags & UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS_IMMED) != 0) + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Send the flush command to the local media. */ + status = storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_flush(storage, lun, number_blocks, lba, &media_status); + + /* Update the request sense. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = (UCHAR) (media_status & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = (UCHAR) ((media_status >> 8 ) & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = (UCHAR) ((media_status >> 16 ) & 0xff); + + /* If the immediate bit is set, we are already done, no matter what local operation status is. */ + if ((flags & UX_SLAVE_CLASS_STORAGE_SYNCHRONIZE_CACHE_FLAGS_IMMED) != 0) + return(status); + + /* If there is a problem, return a failed command. */ + if (status != UX_SUCCESS) + { + + /* We have a problem, request error. Return a bad completion and wait for the + REQUEST_SENSE command. */ + _ux_device_stack_endpoint_stall(endpoint_in); + + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* Return an error. */ + return(UX_ERROR); + } + else + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Return completion status. */ + return(status); +} diff --git a/common/usbx_device_classes/src/ux_device_class_storage_test_ready.c b/common/usbx_device_classes/src/ux_device_class_storage_test_ready.c new file mode 100644 index 0000000..8444133 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_test_ready.c @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_test_ready PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function tests if the SCSI slave device is ready. */ +/* The status function of the storage devices is called. If there is */ +/* an error, the request sense parameters are set for the host to */ +/* investigate. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_class_storage_media_status) Get media status */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_test_ready(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + +UINT status; +ULONG media_status; + + UX_PARAMETER_NOT_USED(cbwcb); + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_TEST_READY, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the status of the device. */ + status = storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_status(storage, lun, + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_id, &media_status); + + /* Set the sense/code/qualifier codes for the REQUEST_SENSE command. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = (media_status & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = ((media_status >> 8) & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = ((media_status >> 16) & 0xff); + + /* Check the status for error. */ + if (status != UX_SUCCESS) + { + + /* We return a CSW with error. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + } + else + { + + /* We return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_thread.c b/common/usbx_device_classes/src/ux_device_class_storage_thread.c new file mode 100644 index 0000000..790fec3 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_thread.c @@ -0,0 +1,417 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the thread of the storage class. */ +/* */ +/* INPUT */ +/* */ +/* class Address of storage class */ +/* container */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_format Storage class format */ +/* _ux_device_class_storage_inquiry Storage class inquiry */ +/* _ux_device_class_storage_mode_select Mode select */ +/* _ux_device_class_storage_mode_sense Mode sense */ +/* _ux_device_class_storage_prevent_allow_media_removal */ +/* Prevent media removal */ +/* _ux_device_class_storage_read Read */ +/* _ux_device_class_storage_read_capacity */ +/* Read capacity */ +/* _ux_device_class_storage_read_format_capacity */ +/* Read format capacity */ +/* _ux_device_class_storage_request_sense */ +/* Sense request */ +/* _ux_device_class_storage_start_stop Start/Stop */ +/* _ux_device_class_storage_synchronize_cache */ +/* Synchronize cache */ +/* _ux_device_class_storage_test_ready Ready test */ +/* _ux_device_class_storage_verify Verify */ +/* _ux_device_class_storage_write Write */ +/* _ux_device_stack_endpoint_stall Endpoint stall */ +/* _ux_device_stack_interface_delete Interface delete */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_get Get 32-bit value */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_utility_thread_suspend Suspend thread */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_device_class_storage_thread(ULONG storage_class) +{ + +UX_SLAVE_CLASS *class; +UX_SLAVE_CLASS_STORAGE *storage; +UX_SLAVE_TRANSFER *transfer_request; +UX_SLAVE_DEVICE *device; +UX_SLAVE_INTERFACE *interface; +UX_SLAVE_ENDPOINT *endpoint_in; +UX_SLAVE_ENDPOINT *endpoint_out; +UINT status; +ULONG length; +ULONG cbwcb_length; +ULONG lun; +UCHAR *scsi_command; + + + /* This thread runs forever but can be suspended or resumed. */ + while(1) + { + + /* Cast properly the storage instance. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_SLAVE_CLASS, storage_class) + + /* Get the storage instance from this class container. */ + storage = (UX_SLAVE_CLASS_STORAGE *) class -> ux_slave_class_instance; + + /* Get the pointer to the device. */ + device = &_ux_system_slave -> ux_system_slave_device; + + /* This is the first time we are activated. We need the interface to the class. */ + interface = storage -> ux_slave_class_storage_interface; + + /* Locate the endpoints. */ + endpoint_in = interface -> ux_slave_interface_first_endpoint; + + /* Check the endpoint direction, if IN we have the correct endpoint. */ + if ((endpoint_in -> ux_slave_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) != UX_ENDPOINT_IN) + { + + /* Wrong direction, we found the OUT endpoint first. */ + endpoint_out = endpoint_in; + + /* So the next endpoint has to be the IN endpoint. */ + endpoint_in = endpoint_out -> ux_slave_endpoint_next_endpoint; + } + else + { + + /* We found the endpoint IN first, so next endpoint is OUT. */ + endpoint_out = endpoint_in -> ux_slave_endpoint_next_endpoint; + } + + /* All SCSI commands are on the endpoint OUT, from the host. */ + transfer_request = &endpoint_out -> ux_slave_endpoint_transfer_request; + + /* As long as the device is in the CONFIGURED state. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* We assume the worst situation. */ + status = UX_ERROR; + + /* Check state, they must be both RESET. */ + if (endpoint_out -> ux_slave_endpoint_state == UX_ENDPOINT_RESET && + !storage -> ux_slave_class_storage_phase_error) + { + + /* Send the request to the device controller. */ + status = _ux_device_stack_transfer_request(transfer_request, 64, 64); + + } + + /* Check the status. Our status is UX_ERROR if one of the endpoint was STALLED. We must wait for the host + to clear the mess. */ + if (status == UX_SUCCESS) + { + + /* Obtain the length of the transaction. */ + length = transfer_request -> ux_slave_transfer_request_actual_length; + + /* Obtain the buffer address containing the SCSI command. */ + scsi_command = transfer_request -> ux_slave_transfer_request_data_pointer; + + /* Obtain the lun from the CBW. */ + lun = (ULONG) *(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_LUN); + + /* We have to memorize the SCSI command tag for the CSW phase. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_scsi_tag = _ux_utility_long_get(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_TAG); + + /* Ensure the LUN number is within our declared values and check the command + content and format. First we make sure we have a complete CBW. */ + if ((lun < storage -> ux_slave_class_storage_number_lun) && (length == UX_SLAVE_CLASS_STORAGE_CBW_LENGTH)) + { + + /* The length of the CBW is correct, analyze the header. */ + if (_ux_utility_long_get(scsi_command) == UX_SLAVE_CLASS_STORAGE_CBW_SIGNATURE_MASK) + { + + /* Get the length of the CBWCB. */ + cbwcb_length = (ULONG) *(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB_LENGTH); + + /* Check the length of the CBWCB to ensure there is at least a command. */ + if (cbwcb_length != 0) + { + + /* Analyze the command stored in the CBWCB. */ + switch (*(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB)) + { + + case UX_SLAVE_CLASS_STORAGE_SCSI_TEST_READY: + + _ux_device_class_storage_test_ready(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_REQUEST_SENSE: + + _ux_device_class_storage_request_sense(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_FORMAT: + + _ux_device_class_storage_format(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_INQUIRY: + + _ux_device_class_storage_inquiry(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_START_STOP: + + _ux_device_class_storage_start_stop(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_PREVENT_ALLOW_MEDIA_REMOVAL: + + _ux_device_class_storage_prevent_allow_media_removal(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ_FORMAT_CAPACITY: + + _ux_device_class_storage_read_format_capacity(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ_CAPACITY: + + _ux_device_class_storage_read_capacity(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_VERIFY: + + _ux_device_class_storage_verify(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SELECT: + + _ux_device_class_storage_mode_select(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT: + case UX_SLAVE_CLASS_STORAGE_SCSI_MODE_SENSE: + + _ux_device_class_storage_mode_sense(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ32: + + _ux_device_class_storage_read(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB, + UX_SLAVE_CLASS_STORAGE_SCSI_READ32); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ16: + + _ux_device_class_storage_read(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB, + UX_SLAVE_CLASS_STORAGE_SCSI_READ16); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32: + + _ux_device_class_storage_write(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB, + UX_SLAVE_CLASS_STORAGE_SCSI_WRITE32); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16: + + _ux_device_class_storage_write(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB, + UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_SYNCHRONIZE_CACHE: + + _ux_device_class_storage_synchronize_cache(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB, *(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB)); + break; + +#ifdef UX_SLAVE_CLASS_STORAGE_INCLUDE_MMC + case UX_SLAVE_CLASS_STORAGE_SCSI_GET_STATUS_NOTIFICATION: + + _ux_device_class_storage_get_status_notification(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_GET_CONFIGURATION: + + _ux_device_class_storage_get_configuration(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ_DISK_INFORMATION: + + _ux_device_class_storage_read_disk_information(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_REPORT_KEY: + + _ux_device_class_storage_report_key(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_GET_PERFORMANCE: + + _ux_device_class_storage_get_performance(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ_DVD_STRUCTURE: + + _ux_device_class_storage_read_dvd_structure(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + break; + + case UX_SLAVE_CLASS_STORAGE_SCSI_READ_TOC: + + status = _ux_device_class_storage_read_toc(storage, lun, endpoint_in, endpoint_out, scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_CB); + + /* Special treatment of TOC command. If error, default to Stall endpoint. */ + if (status == UX_SUCCESS) + break; + /* fall through */ +#endif + + default: + + /* The command is unknown or unsupported, so we stall the endpoint. */ + + if (_ux_utility_long_get(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_DATA_LENGTH) > 0 && + ((*(scsi_command + UX_SLAVE_CLASS_STORAGE_CBW_FLAGS) & 0x80) == 0)) + + /* Data-Out from host to device, stall OUT. */ + _ux_device_stack_endpoint_stall(endpoint_out); + else + + /* Data-In from device to host, stall IN. */ + _ux_device_stack_endpoint_stall(endpoint_in); + + /* Initialize the request sense keys. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = UX_SLAVE_CLASS_STORAGE_SENSE_KEY_ILLEGAL_REQUEST; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = UX_SLAVE_CLASS_STORAGE_ASC_KEY_INVALID_COMMAND; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0; + + /* This is the tricky part of the SCSI state machine. We must send the CSW BUT need to wait + for the endpoint_in to be reset by the host. */ + while (device -> ux_slave_device_state == UX_DEVICE_CONFIGURED) + { + + /* Check the endpoint state. */ + if (endpoint_in -> ux_slave_endpoint_state == UX_ENDPOINT_RESET) + { + + /* Now we return a CSW with failure. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* Check error code. */ + if (status != UX_SUCCESS) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + + break; + } + + else + + /* We must therefore wait a while. */ + _ux_utility_thread_relinquish(); + } + break; + } + } + else + + /* Phase error! */ + storage -> ux_slave_class_storage_phase_error = TX_TRUE; + } + + else + + /* Phase error! */ + storage -> ux_slave_class_storage_phase_error = TX_TRUE; + } + else + + /* Phase error! */ + storage -> ux_slave_class_storage_phase_error = TX_TRUE; + } + else + { + + if (storage -> ux_slave_class_storage_phase_error == TX_TRUE) + { + + /* We should keep the endpoints stalled. */ + _ux_device_stack_endpoint_stall(endpoint_out); + _ux_device_stack_endpoint_stall(endpoint_in); + } + + /* We must therefore wait a while. */ + _ux_utility_thread_relinquish(); + } + } + + /* We need to suspend ourselves. We will be resumed by the + device enumeration module. */ + _ux_utility_thread_suspend(&class -> ux_slave_class_thread); + } +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_uninitialize.c b/common/usbx_device_classes/src/ux_device_class_storage_uninitialize.c new file mode 100644 index 0000000..112225a --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_uninitialize.c @@ -0,0 +1,100 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_uninitialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deinitializes the USB storage device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to storage command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_thread_delete Delete thread */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_uninitialize(UX_SLAVE_CLASS_COMMAND *command) +{ + +UX_SLAVE_CLASS_STORAGE *storage; +UX_SLAVE_CLASS *class; + + /* Get the class container. */ + class = command -> ux_slave_class_command_class_ptr; + + /* Get the class instance in the container. */ + storage = (UX_SLAVE_CLASS_STORAGE *) class -> ux_slave_class_instance; + + /* Sanity check. */ + if (storage != UX_NULL) + { + + /* Remove STORAGE thread. */ + _ux_utility_thread_delete(&class -> ux_slave_class_thread); + + /* Remove the thread used by STORAGE. */ + _ux_utility_memory_free(class -> ux_slave_class_thread_stack); + + /* Free the resources. */ + _ux_utility_memory_free(storage); + } + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_verify.c b/common/usbx_device_classes/src/ux_device_class_storage_verify.c new file mode 100644 index 0000000..c915ec6 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_verify.c @@ -0,0 +1,91 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_verify PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function verifies a previous write command. */ +/* Here, the CSW is returned with a SUCCESS code. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to CBWCB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_verify(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb) +{ + + UX_PARAMETER_NOT_USED(cbwcb); + UX_PARAMETER_NOT_USED(endpoint_out); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_VERIFY, storage, lun, 0, 0, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* We return a CSW with success. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Return success! */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_device_classes/src/ux_device_class_storage_write.c b/common/usbx_device_classes/src/ux_device_class_storage_write.c new file mode 100644 index 0000000..dbf0b49 --- /dev/null +++ b/common/usbx_device_classes/src/ux_device_class_storage_write.c @@ -0,0 +1,238 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Device Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define UX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "ux_api.h" +#include "ux_device_class_storage.h" +#include "ux_device_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_device_class_storage_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a WRITE command in 32 or 16 bits. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* endpoint_in Pointer to IN endpoint */ +/* endpoint_out Pointer to OUT endpoint */ +/* cbwcb Pointer to the CBWCB */ +/* scsi_command SCSI command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_slave_class_storage_media_status) Get media status */ +/* (ux_slave_class_storage_media_write) Write to media */ +/* _ux_device_class_storage_csw_send Send CSW */ +/* _ux_device_stack_endpoint_stall Stall endpoint */ +/* _ux_device_stack_transfer_request Transfer request */ +/* _ux_utility_long_get_big_endian Get 32-bit big endian */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Release memory */ +/* _ux_utility_long_get_big_endian Get 32-bit big endian */ +/* _ux_utility_short_get_big_endian Get 16-bit big endian */ +/* */ +/* CALLED BY */ +/* */ +/* Device Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_device_class_storage_write(UX_SLAVE_CLASS_STORAGE *storage, ULONG lun, + UX_SLAVE_ENDPOINT *endpoint_in, + UX_SLAVE_ENDPOINT *endpoint_out, UCHAR * cbwcb, UCHAR scsi_command) +{ + +UINT status; +UX_SLAVE_TRANSFER *transfer_request; +ULONG lba; +ULONG total_number_blocks; +ULONG number_blocks; +ULONG media_status; +ULONG total_length; +ULONG transfer_length; + + /* Get the LBA from the CBWCB. */ + lba = _ux_utility_long_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_WRITE_LBA); + + /* The type of commands will tell us the width of the field containing the number + of sectors to read. */ + if (scsi_command == UX_SLAVE_CLASS_STORAGE_SCSI_WRITE16) + + /* Get the number of blocks from the CBWCB in 16 bits. */ + total_number_blocks = _ux_utility_short_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_WRITE_TRANSFER_LENGTH_16); + + else + + /* Get the number of blocks from the CBWCB in 32 bits. */ + total_number_blocks = _ux_utility_long_get_big_endian(cbwcb + UX_SLAVE_CLASS_STORAGE_WRITE_TRANSFER_LENGTH_32); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_DEVICE_CLASS_STORAGE_WRITE, storage, lun, lba, total_number_blocks, UX_TRACE_DEVICE_CLASS_EVENTS, 0, 0) + + /* Obtain the pointer to the transfer request. */ + transfer_request = &endpoint_out -> ux_slave_endpoint_transfer_request; + + /* Obtain the status of the device. */ + status = storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_status(storage, + lun, storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_id, &media_status); + + /* Update the request sense. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = (UCHAR) (media_status & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = (UCHAR) ((media_status >> 8 ) & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = (UCHAR) ((media_status >> 16 ) & 0xff); + + /* If there is a problem, return a failed command. */ + if (status != UX_SUCCESS) + { + + /* We have a problem, media status error. Return a bad completion and wait for the + REQUEST_SENSE command. */ + _ux_device_stack_endpoint_stall(endpoint_out); + + /* Now we return a CSW with failure. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* We are done here. */ + return(UX_ERROR); + } + + /* Check Read Only flag. */ + if (storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_read_only_flag == UX_TRUE) + { + + /* Update the request sense. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = UX_SLAVE_CLASS_STORAGE_SENSE_KEY_DATA_PROTECT; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = UX_SLAVE_CLASS_STORAGE_REQUEST_CODE_MEDIA_PROTECTED; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0; + + /* We have a problem, cannot write to RO drive. Return a bad completion and wait for the + REQUEST_SENSE command. */ + _ux_device_stack_endpoint_stall(endpoint_out); + + /* Now we return a CSW with failure. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* We are done here. */ + return(UX_ERROR); + } + + /* Compute the total length to transfer and how much remains. */ + total_length = total_number_blocks * storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_block_length; + + /* Default status to success. */ + status = UX_SUCCESS; + + /* It may take several transfers to send the requested data. */ + while (total_length) + { + + /* How much can we receive in this transfer? */ + if (total_length > UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE) + transfer_length = UX_SLAVE_CLASS_STORAGE_BUFFER_SIZE; + else + transfer_length = total_length; + + /* Get the data payload from the host. */ + status = _ux_device_stack_transfer_request(transfer_request, transfer_length, transfer_length); + + /* Check the status. */ + if (status != UX_SUCCESS) + { + + /* We have a problem, request error. Return a bad completion and wait for the + REQUEST_SENSE command. */ + _ux_device_stack_endpoint_stall(endpoint_out); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = 0x02; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = 0x54; + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = 0x00; + + /* Now we return a CSW with failure. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* Return an error. */ + return(UX_ERROR); + } + + /* Compute the number of blocks to transfer. */ + number_blocks = transfer_length / storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_block_length; + + /* Execute the write command to the local media. */ + status = storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_media_write(storage, lun, transfer_request -> ux_slave_transfer_request_data_pointer, number_blocks, lba, &media_status); + + /* If there is a problem, return a failed command. */ + if (status != UX_SUCCESS) + { + + /* We have a problem, request error. Return a bad completion and wait for the + REQUEST_SENSE command. */ + _ux_device_stack_endpoint_stall(endpoint_out); + + /* And update the REQUEST_SENSE codes. */ + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_sense_key = (UCHAR) (media_status & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code = (UCHAR) ((media_status >> 8 ) & 0xff); + storage -> ux_slave_class_storage_lun[lun].ux_slave_class_storage_request_code_qualifier = (UCHAR) ((media_status >> 16 ) & 0xff); + + /* Now we return a CSW with failure. */ + _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_FAILED); + + /* Return an error. */ + return(UX_ERROR); + } + + /* Update the lba. */ + lba += number_blocks; + + /* Update the length to remain. */ + total_length -= transfer_length; + } + + /* Now we return a CSW with success. */ + status = _ux_device_class_storage_csw_send(storage, lun, endpoint_in, UX_SLAVE_CLASS_STORAGE_CSW_PASSED); + + /* Return completion status. */ + return(status); +} diff --git a/common/usbx_host_classes/CMakeLists.txt b/common/usbx_host_classes/CMakeLists.txt new file mode 100644 index 0000000..5be86cc --- /dev/null +++ b/common/usbx_host_classes/CMakeLists.txt @@ -0,0 +1,267 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_interrupt_notification.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_reception_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_setup.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_transmission_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_asix_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_alternate_setting_locate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_control_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_control_value_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_control_value_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_descriptor_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_device_controls_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_device_type_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_streaming_sampling_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_streaming_sampling_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_streaming_terminal_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_audio_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_capabilities_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_command.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_reception_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_reception_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_reception_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_acm_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_interrupt_notification.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_mac_address_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_transmission_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_transmit_queue_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_cdc_ecm_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_command.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_reception_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_reception_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_reception_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_gser_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_client_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_client_search.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_descriptor_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_field_decompress.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_global_item_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_idle_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_idle_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_instance_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_interrupt_endpoint_search.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_item_data_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_key_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_keyboard_thread.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_local_item_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_main_item_parse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_buttons_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_position_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_mouse_wheel_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_periodic_report_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_periodic_report_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_remote_control_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_remote_control_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_remote_control_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_remote_control_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_remote_control_usage_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_callback_register.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_compress.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_decompress.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_descriptor_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_id_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_item_analyse.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_report_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_resources_free.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hid_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_change_detect.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_change_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_descriptor_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_feature.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_hub_change_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_interrupt_endpoint_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_connection_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_enable_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_over_current_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_reset_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_change_suspend_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_ports_power.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_hub_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_command.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_device_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_device_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_notification.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_num_objects_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_close.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_copy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_handles_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_info_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_move.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_open.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_send.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_object_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_request_cancel.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_session_close.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_session_open.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_storage_ids_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_storage_info_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_thumb_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_pima_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_name_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_soft_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_printer_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_command.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_reception_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_reception_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_reception_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_setup.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_transfer_request_completed.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_prolific_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_cbw_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_device_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_device_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_device_support_check.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_driver_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_max_lun_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_capacity_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_characteristics_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_format_capacity_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_mount.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_open.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_protection_check.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_recovery_sense_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_media_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_partition_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_request_sense.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_sense_code_translate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_start_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_thread_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport_bo.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport_cb.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_transport_cbi.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_storage_unit_ready_test.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_reception_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_reception_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_reception_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_swar_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_activate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_alternate_setting_locate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_channel_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_configure.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_control_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_control_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_control_value_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_control_value_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_deactivate.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_descriptor_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_endpoints_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_format_data_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_frame_data_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_frame_interval_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_frame_parameters_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_input_format_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_input_terminal_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_ioctl.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_max_payload_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_start.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_stop.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_transfer_buffer_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_transfer_buffers_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_transfer_callback_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_transfer_request.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_transfer_request_callback.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_host_class_video_transfer_request_completed.c + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/common/usbx_host_classes/inc/ux_host_class_asix.h b/common/usbx_host_classes/inc/ux_host_class_asix.h new file mode 100644 index 0000000..71d1083 --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_asix.h @@ -0,0 +1,413 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** ASIX Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_asix.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX ASIX class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_ASIX_H +#define UX_HOST_CLASS_ASIX_H + + +#include "nx_api.h" +#include "ux_network_driver.h" + +/* Define to check if NetX preserved header size is compatible with ASIX. */ +/* #define UX_HOST_CLASS_ASIX_HEADER_CHECK_ENABLE */ + + +/* Define ASIX Class constants. Insert here the PID/VID of vendors and products using the Asix chipset. */ +#ifndef UX_HOST_CLASS_ASIX_VENDOR_ID +#define UX_HOST_CLASS_ASIX_VENDOR_ID 0X2001 +#define UX_HOST_CLASS_ASIX_PRODUCT_ID 0X3C05 +#endif + +#define UX_HOST_CLASS_ASIX_VENDOR_FUJIEI_ID 0X0B95 +#define UX_HOST_CLASS_ASIX_PRODUCT_FUJIEI_ID 0X772B + +#define UX_HOST_CLASS_ASIX_SPEED_SELECTED_100MPBS 0x100 +#define UX_HOST_CLASS_ASIX_SPEED_SELECTED_10MPBS 0x10 +#define UX_HOST_CLASS_ASIX_LINK_STATE_DOWN 0 +#define UX_HOST_CLASS_ASIX_LINK_STATE_UP 1 +#define UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_UP 2 +#define UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_DOWN 3 +#define UX_HOST_CLASS_ASIX_BASE_IP_ADDRESS 0xC0A80001 +#define UX_HOST_CLASS_ASIX_BASE_IP_MASK 0xFFFFFF00 +#define UX_HOST_CLASS_ASIX_MAX_MTU 1518 +#define UX_HOST_CLASS_ASIX_ETHERNET_IP 0x0800 +#define UX_HOST_CLASS_ASIX_ETHERNET_ARP 0x0806 +#define UX_HOST_CLASS_ASIX_ETHERNET_RARP 0x8035 +#define UX_HOST_CLASS_ASIX_ETHERNET_PACKET_SIZE 1536 +#define UX_HOST_CLASS_ASIX_NX_ALIGN_PADDING 2 +#ifndef UX_HOST_CLASS_ASIX_NX_PKPOOL_ENTRIES +#define UX_HOST_CLASS_ASIX_NX_PKPOOL_ENTRIES 16 +#endif + +#define UX_HOST_CLASS_ASIX_NX_PACKET_SIZE sizeof(NX_PACKET) + +#define UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE_ASSERT UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG(UX_HOST_CLASS_ASIX_ETHERNET_PACKET_SIZE, UX_HOST_CLASS_ASIX_NX_ALIGN_PADDING), UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE_calc_ovf) +#define UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE (UX_HOST_CLASS_ASIX_ETHERNET_PACKET_SIZE + UX_HOST_CLASS_ASIX_NX_ALIGN_PADDING) + +#define UX_HOST_CLASS_ASIX_NX_BUFF_SIZE_ASSERT \ + UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE_ASSERT \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG( \ + UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE, \ + UX_HOST_CLASS_ASIX_NX_PACKET_SIZE), \ + UX_HOST_CLASS_ASIX_NX_BUFF_SIZE_calc_ovf) +#define UX_HOST_CLASS_ASIX_NX_BUFF_SIZE (UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE + UX_HOST_CLASS_ASIX_NX_PACKET_SIZE) + +#define UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT \ + UX_HOST_CLASS_ASIX_NX_BUFF_SIZE_ASSERT \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG( \ + UX_HOST_CLASS_ASIX_NX_PKPOOL_ENTRIES, \ + UX_HOST_CLASS_ASIX_NX_BUFF_SIZE), \ + UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_calc1_ovf) \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG( \ + UX_HOST_CLASS_ASIX_NX_PKPOOL_ENTRIES * \ + UX_HOST_CLASS_ASIX_NX_BUFF_SIZE, \ + 32), UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_calc2_ovf) +#define UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE (UX_HOST_CLASS_ASIX_NX_PKPOOL_ENTRIES * UX_HOST_CLASS_ASIX_NX_BUFF_SIZE + 32) + +#define UX_HOST_CLASS_ASIX_ETHERNET_SIZE 14 + +#define UX_HOST_CLASS_ASIX_DEVICE_INIT_DELAY (1 * UX_PERIODIC_RATE) +#define UX_HOST_CLASS_ASIX_CLASS_TRANSFER_TIMEOUT 300000 +#define UX_HOST_CLASS_ASIX_SETUP_BUFFER_SIZE 16 + +/* Define NetX errors inside the Asix class. */ +#define UX_HOST_CLASS_ASIX_NX_SUCCESS 0x00 +#define UX_HOST_CLASS_ASIX_NX_NO_PACKET 0x01 +#define UX_HOST_CLASS_ASIX_NX_UNDERFLOW 0x02 +#define UX_HOST_CLASS_ASIX_NX_OVERFLOW 0x03 +#define UX_HOST_CLASS_ASIX_NX_NO_MAPPING 0x04 +#define UX_HOST_CLASS_ASIX_NX_DELETED 0x05 +#define UX_HOST_CLASS_ASIX_NX_POOL_ERROR 0x06 +#define UX_HOST_CLASS_ASIX_NX_PTR_ERROR 0x07 +#define UX_HOST_CLASS_ASIX_NX_WAIT_ERROR 0x08 +#define UX_HOST_CLASS_ASIX_NX_SIZE_ERROR 0x09 +#define UX_HOST_CLASS_ASIX_NX_OPTION_ERROR 0x0a +#define UX_HOST_CLASS_ASIX_NX_DELETE_ERROR 0x10 +#define UX_HOST_CLASS_ASIX_NX_CALLER_ERROR 0x11 +#define UX_HOST_CLASS_ASIX_NX_INVALID_PACKET 0x12 +#define UX_HOST_CLASS_ASIX_NX_INVALID_SOCKET 0x13 +#define UX_HOST_CLASS_ASIX_NX_NOT_ENABLED 0x14 +#define UX_HOST_CLASS_ASIX_NX_ALREADY_ENABLED 0x15 +#define UX_HOST_CLASS_ASIX_NX_ENTRY_NOT_FOUND 0x16 +#define UX_HOST_CLASS_ASIX_NX_NO_MORE_ENTRIES 0x17 +#define UX_HOST_CLASS_ASIX_NX_ARP_TIMER_ERROR 0x18 +#define UX_HOST_CLASS_ASIX_NX_RESERVED_CODE0 0x19 +#define UX_HOST_CLASS_ASIX_NX_WAIT_ABORTED 0x1A +#define UX_HOST_CLASS_ASIX_NX_IP_INTERNAL_ERROR 0x20 +#define UX_HOST_CLASS_ASIX_NX_IP_ADDRESS_ERROR 0x21 +#define UX_HOST_CLASS_ASIX_NX_ALREADY_BOUND 0x22 +#define UX_HOST_CLASS_ASIX_NX_PORT_UNAVAILABLE 0x23 +#define UX_HOST_CLASS_ASIX_NX_NOT_BOUND 0x24 +#define UX_HOST_CLASS_ASIX_NX_RESERVED_CODE1 0x25 +#define UX_HOST_CLASS_ASIX_NX_SOCKET_UNBOUND 0x26 +#define UX_HOST_CLASS_ASIX_NX_NOT_CREATED 0x27 +#define UX_HOST_CLASS_ASIX_NX_SOCKETS_BOUND 0x28 +#define UX_HOST_CLASS_ASIX_NX_NO_RESPONSE 0x29 +#define UX_HOST_CLASS_ASIX_NX_POOL_DELETED 0x30 +#define UX_HOST_CLASS_ASIX_NX_ALREADY_RELEASED 0x31 +#define UX_HOST_CLASS_ASIX_NX_RESERVED_CODE2 0x32 +#define UX_HOST_CLASS_ASIX_NX_MAX_LISTEN 0x33 +#define UX_HOST_CLASS_ASIX_NX_DUPLICATE_LISTEN 0x34 +#define UX_HOST_CLASS_ASIX_NX_NOT_CLOSED 0x35 +#define UX_HOST_CLASS_ASIX_NX_NOT_LISTEN_STATE 0x36 +#define UX_HOST_CLASS_ASIX_NX_IN_PROGRESS 0x37 +#define UX_HOST_CLASS_ASIX_NX_NOT_CONNECTED 0x38 +#define UX_HOST_CLASS_ASIX_NX_WINDOW_OVERFLOW 0x39 +#define UX_HOST_CLASS_ASIX_NX_ALREADY_SUSPENDED 0x40 +#define UX_HOST_CLASS_ASIX_NX_DISCONNECT_FAILED 0x41 +#define UX_HOST_CLASS_ASIX_NX_STILL_BOUND 0x42 +#define UX_HOST_CLASS_ASIX_NX_NOT_SUCCESSFUL 0x43 +#define UX_HOST_CLASS_ASIX_NX_UNHANDLED_COMMAND 0x44 +#define UX_HOST_CLASS_ASIX_NX_NO_FREE_PORTS 0x45 +#define UX_HOST_CLASS_ASIX_NX_INVALID_PORT 0x46 +#define UX_HOST_CLASS_ASIX_NX_INVALID_RELISTEN 0x47 +#define UX_HOST_CLASS_ASIX_NX_CONNECTION_PENDING 0x48 +#define UX_HOST_CLASS_ASIX_NX_TX_QUEUE_DEPTH 0x49 +#define UX_HOST_CLASS_ASIX_NX_NOT_IMPLEMENTED 0x80 + + + +/* Define ASIX command request values. */ + +#define UX_HOST_CLASS_ASIX_REQ_RX_TX_SRAM_REG_READ 0x02 +#define UX_HOST_CLASS_ASIX_REQ_RX_TX_SRAM_REG_WRITE 0x03 +#define UX_HOST_CLASS_ASIX_REQ_OWN_SMI 0x06 +#define UX_HOST_CLASS_ASIX_REQ_READ_PHY_REG 0x07 +#define UX_HOST_CLASS_ASIX_REQ_WRITE_PHY_REG 0x08 +#define UX_HOST_CLASS_ASIX_REQ_WHO_OWNS_SMI 0x09 +#define UX_HOST_CLASS_ASIX_REQ_RELEASE_SMI 0x0a +#define UX_HOST_CLASS_ASIX_REQ_READ_SROM 0x0b +#define UX_HOST_CLASS_ASIX_REQ_WRITE_SROM 0x0c +#define UX_HOST_CLASS_ASIX_REQ_WRITE_SROM_EN 0x0d +#define UX_HOST_CLASS_ASIX_REQ_WRITE_SROM_DIS 0x0e +#define UX_HOST_CLASS_ASIX_REQ_READ_RX_CTL 0x0f +#define UX_HOST_CLASS_ASIX_REQ_WRITE_RX_CTL 0x10 +#define UX_HOST_CLASS_ASIX_REQ_READ_IPG012 0x11 +#define UX_HOST_CLASS_ASIX_REQ_WRITE_IPG012 0x12 +#define UX_HOST_CLASS_ASIX_REQ_READ_NODE_ID 0x13 +#define UX_HOST_CLASS_ASIX_REQ_WRITE_NODE_ID 0x14 +#define UX_HOST_CLASS_ASIX_REQ_WRITE_MULTICAST_FILTER 0x16 +#define UX_HOST_CLASS_ASIX_REQ_TEST_REGISTER 0x17 +#define UX_HOST_CLASS_ASIX_REQ_READ_PHY_ID 0x19 +#define UX_HOST_CLASS_ASIX_REQ_READ_MEDIUM_STATUS 0x1a +#define UX_HOST_CLASS_ASIX_REQ_WRITE_MEDIUM_MODE 0x1b +#define UX_HOST_CLASS_ASIX_REQ_READ_MONITOR_MODE_STATUS 0x1c +#define UX_HOST_CLASS_ASIX_REQ_WRITE_MONITOR_MODE_STATUS 0x1d +#define UX_HOST_CLASS_ASIX_REQ_READ_GPIO_STATUS 0x1e +#define UX_HOST_CLASS_ASIX_REQ_WRITE_GPIO_STATUS 0x1f +#define UX_HOST_CLASS_ASIX_REQ_SW_RESET 0x20 +#define UX_HOST_CLASS_ASIX_REQ_READ_SW_PHY_SELECT_STATUS 0x21 +#define UX_HOST_CLASS_ASIX_REQ_WRITE_SW_PHY_SELECT_STATUS 0x22 + +/* Define ASIX Interrupt Packet format. */ + +#define UX_HOST_CLASS_ASIX_INTERRUPT_SIGNATURE_VALUE 0xA1 +#define UX_HOST_CLASS_ASIX_INTERRUPT_SIGNATURE_OFFSET 0x00 +#define UX_HOST_CLASS_ASIX_INTERRUPT_STATE_OFFSET 0x02 +#define UX_HOST_CLASS_ASIX_INTERRUPT_STATE_PPLS 0x01 +#define UX_HOST_CLASS_ASIX_INTERRUPT_STATE_SPLS 0x02 +#define UX_HOST_CLASS_ASIX_INTERRUPT_STATE_FLE 0x04 +#define UX_HOST_CLASS_ASIX_INTERRUPT_STATE_MDINT 0x08 +#define UX_HOST_CLASS_ASIX_INTERRUPT_PHY_REG_VALUE_OFFSET 0x05 + +/* Define ASIX Class PHY ID Packet format. */ + +#define UX_HOST_CLASS_ASIX_PHY_ID_SECONDARY 0x00 +#define UX_HOST_CLASS_ASIX_PHY_ID_PRIMARY 0x01 +#define UX_HOST_CLASS_ASIX_PHY_ID_MASK 0x01f +#define UX_HOST_CLASS_ASIX_PHY_TYPE_SHIFT 0x05 +#define UX_HOST_CLASS_ASIX_PHY_TYPE_MASK 0x07 + +/* Define ASIX Class GPIO Register. */ + +#define UX_HOST_CLASS_ASIX_GPIO_GPO0EN 0x01 +#define UX_HOST_CLASS_ASIX_GPIO_GPO_0 0x02 +#define UX_HOST_CLASS_ASIX_GPIO_GPO1EN 0x04 +#define UX_HOST_CLASS_ASIX_GPIO_GPO_1 0x08 +#define UX_HOST_CLASS_ASIX_GPIO_GPO2EN 0x10 +#define UX_HOST_CLASS_ASIX_GPIO_GPO_2 0x20 +#define UX_HOST_CLASS_ASIX_GPIO_RSE 0x80 + +/* Define ASIX Class Software reset Register. */ + +#define UX_HOST_CLASS_ASIX_SW_RESET_RR 0x01 +#define UX_HOST_CLASS_ASIX_SW_RESET_RT 0x02 +#define UX_HOST_CLASS_ASIX_SW_RESET_PRTE 0x04 +#define UX_HOST_CLASS_ASIX_SW_RESET_PRL 0x08 +#define UX_HOST_CLASS_ASIX_SW_RESET_BZ 0x10 +#define UX_HOST_CLASS_ASIX_SW_RESET_IPRL 0x20 +#define UX_HOST_CLASS_ASIX_SW_RESET_IPPD 0x40 + +/* Define ASIX Class Receive Control Register. */ + +#define UX_HOST_CLASS_ASIX_RXCR_PRO 0x0001 +#define UX_HOST_CLASS_ASIX_RXCR_AMALL 0x0002 +#define UX_HOST_CLASS_ASIX_RXCR_SEP 0x0004 +#define UX_HOST_CLASS_ASIX_RXCR_AB 0x0008 +#define UX_HOST_CLASS_ASIX_RXCR_AM 0x0010 +#define UX_HOST_CLASS_ASIX_RXCR_AP 0x0020 +#define UX_HOST_CLASS_ASIX_RXCR_SO 0x0080 + +#define UX_HOST_CLASS_ASIX_RXCR_MFB_2048 0x0000 +#define UX_HOST_CLASS_ASIX_RXCR_MFB_4096 0x0100 +#define UX_HOST_CLASS_ASIX_RXCR_MFB_8192 0x0200 +#define UX_HOST_CLASS_ASIX_RXCR_MFB_16384 0x0300 + +/* Define ASIX Class packet equivalences. */ + +#define UX_HOST_CLASS_ASIX_PACKET_SIZE 128 +#define UX_HOST_CLASS_ASIX_NODE_ID_LENGTH 6 + +/* Define ASIX PHY registers description. */ + +#define UX_HOST_CLASS_ASIX_PHY_REG_BMCR 0x00 +#define UX_HOST_CLASS_ASIX_PHY_REG_BMSR 0x01 +#define UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1 0x02 +#define UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR2 0x03 +#define UX_HOST_CLASS_ASIX_PHY_REG_ANAR 0x04 +#define UX_HOST_CLASS_ASIX_PHY_REG_ANLPAR 0x05 +#define UX_HOST_CLASS_ASIX_PHY_REG_ANER 0x06 + +/* Define ASIX PHY BMCR registers description. */ + +#define UX_HOST_CLASS_ASIX_PHY_REG_BMCR_RESET 0x8000 +#define UX_HOST_CLASS_ASIX_PHY_REG_BMCR_LOOPBACK_ENABLED 0x4000 +#define UX_HOST_CLASS_ASIX_PHY_REG_BMCR_SPEED_100MBS 0x2000 +#define UX_HOST_CLASS_ASIX_PHY_REG_BMCR_SPEED_10MBS 0x0000 +#define UX_HOST_CLASS_ASIX_PHY_REG_BMCR_AUTO_NEGOTIATION 0x1000 +#define UX_HOST_CLASS_ASIX_PHY_REG_BMCR_POWER_DOWN 0x0800 +#define UX_HOST_CLASS_ASIX_PHY_REG_BMCR_ISOLATE 0x0400 +#define UX_HOST_CLASS_ASIX_PHY_REG_BMCR_RESTART_NEG 0x0200 +#define UX_HOST_CLASS_ASIX_PHY_REG_BMCR_DUPLEX_MODE 0x0100 +#define UX_HOST_CLASS_ASIX_PHY_REG_BMCR_COLLISION_TEST 0x0080 + + +/* Define ASIX PHY PHYIDR1 register description. */ + +#define UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_MDL_REV_SHIFT 0x00 +#define UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_MDL_REV_MASK 0x0f +#define UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_VNDR_REV_SHIFT 0x04 +#define UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_VNDR_REV_MASK 0x2f + + +/* Define ASIX PHY ANAR register description. */ + +#define UX_HOST_CLASS_ASIX_PHY_REG_ANAR_DEFAULT_SELECTOR 0x0001 +#define UX_HOST_CLASS_ASIX_PHY_REG_ANAR_10_HD 0x0020 +#define UX_HOST_CLASS_ASIX_PHY_REG_ANAR_10_FD 0x0040 +#define UX_HOST_CLASS_ASIX_PHY_REG_ANAR_TX_HD 0x0080 +#define UX_HOST_CLASS_ASIX_PHY_REG_ANAR_TX_FD 0x0100 +#define UX_HOST_CLASS_ASIX_PHY_REG_ANAR_T4 0x0200 +#define UX_HOST_CLASS_ASIX_PHY_REG_ANAR_PAUSE 0x0400 +#define UX_HOST_CLASS_ASIX_PHY_REG_ANAR_RF 0x1000 +#define UX_HOST_CLASS_ASIX_PHY_REG_ANAR_ACK 0x2000 + +/* Define ASIX MEDIUM register description. */ + +#define UX_HOST_CLASS_ASIX_MEDIUM_FD 0x0002 +#define UX_HOST_CLASS_ASIX_MEDIUM_BIT2 0x0004 +#define UX_HOST_CLASS_ASIX_MEDIUM_BIT3 0x0000 +#define UX_HOST_CLASS_ASIX_MEDIUM_RFC_ENABLED 0x0010 +#define UX_HOST_CLASS_ASIX_MEDIUM_TFC_ENABLED 0x0020 + +#define UX_HOST_CLASS_ASIX_MEDIUM_RE_ENABLED 0x0100 +#define UX_HOST_CLASS_ASIX_MEDIUM_PS 0x0200 +#define UX_HOST_CLASS_ASIX_MEDIUM_SBP 0x0800 +#define UX_HOST_CLASS_ASIX_MEDIUM_SM 0x1000 + +/* Define ASIX IPG default values register description. */ + +#define UX_HOST_CLASS_ASIX_PPG0_IPG1 0x0C15 +#define UX_HOST_CLASS_ASIX_PPG2 0x000E + +/* Define ASIX Reception States. */ + +#define UX_HOST_CLASS_ASIX_RECEPTION_STATE_STOPPED 0 +#define UX_HOST_CLASS_ASIX_RECEPTION_STATE_STARTED 1 +#define UX_HOST_CLASS_ASIX_RECEPTION_STATE_IN_TRANSFER 2 + + +/* Define ASIX Class instance structure. */ + +typedef struct UX_HOST_CLASS_ASIX_STRUCT +{ + struct UX_HOST_CLASS_ASIX_STRUCT + *ux_host_class_asix_next_instance; + UX_HOST_CLASS *ux_host_class_asix_class; + UX_DEVICE *ux_host_class_asix_device; + UX_ENDPOINT *ux_host_class_asix_bulk_in_endpoint; + UX_ENDPOINT *ux_host_class_asix_bulk_out_endpoint; + UX_ENDPOINT *ux_host_class_asix_interrupt_endpoint; + UX_INTERFACE *ux_host_class_asix_interface; + UINT ux_host_class_asix_instance_status; + UINT ux_host_class_asix_state; + TX_SEMAPHORE ux_host_class_asix_semaphore; + TX_SEMAPHORE ux_host_class_asix_interrupt_notification_semaphore; + TX_THREAD ux_host_class_asix_thread; + UCHAR *ux_host_class_asix_thread_stack; + ULONG ux_host_class_asix_notification_count; + ULONG ux_host_class_asix_primary_phy_id; + ULONG ux_host_class_asix_primary_phy_type; + ULONG ux_host_class_asix_secondary_phy_id; + ULONG ux_host_class_asix_secondary_phy_type; + ULONG ux_host_class_asix_model_revision_number; + ULONG ux_host_class_asix_vendor_model_number; + ULONG ux_host_class_asix_speed_selected; + ULONG ux_host_class_asix_device_state; + ULONG ux_host_class_asix_link_state; + NX_PACKET *ux_host_class_asix_xmit_queue; + NX_PACKET *ux_host_class_asix_receive_queue; + NX_PACKET_POOL ux_host_class_asix_packet_pool; + UCHAR *ux_host_class_asix_pool_memory; + UCHAR ux_host_class_asix_node_id[UX_HOST_CLASS_ASIX_NODE_ID_LENGTH]; + VOID (*ux_host_class_asix_device_status_change_callback)(struct UX_HOST_CLASS_ASIX_STRUCT *asix, + ULONG device_state); + VOID *ux_host_class_asix_network_handle; + +} UX_HOST_CLASS_ASIX; + + +/* Define ASIX reception structure. */ + +typedef struct UX_HOST_CLASS_ASIX_RECEPTION_STRUCT +{ + + ULONG ux_host_class_asix_reception_state; + ULONG ux_host_class_asix_reception_block_size; + UCHAR *ux_host_class_asix_reception_data_buffer; + ULONG ux_host_class_asix_reception_data_buffer_size; + UCHAR *ux_host_class_asix_reception_data_head; + UCHAR *ux_host_class_asix_reception_data_tail; + VOID (*ux_host_class_asix_reception_callback)(struct UX_HOST_CLASS_ASIX_STRUCT *asix, + UINT status, + UCHAR *reception_buffer, + ULONG reception_size); + +} UX_HOST_CLASS_ASIX_RECEPTION; + +/* Define Asix Class function prototypes. */ + +UINT _ux_host_class_asix_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_asix_configure(UX_HOST_CLASS_ASIX *asix); +UINT _ux_host_class_asix_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_asix_endpoints_get(UX_HOST_CLASS_ASIX *asix); +UINT _ux_host_class_asix_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_asix_read (UX_HOST_CLASS_ASIX *asix, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_asix_write(VOID *asix_class, NX_PACKET *packet); +VOID _ux_host_class_asix_interrupt_notification(UX_TRANSFER *transfer_request); +VOID _ux_host_class_asix_reception_callback (UX_TRANSFER *transfer_request); +VOID _ux_host_class_asix_thread(ULONG parameter); +VOID _ux_host_class_asix_transmission_callback (UX_TRANSFER *transfer_request); +UINT _ux_host_class_asix_setup(UX_HOST_CLASS_ASIX *asix); + +/* Define Asix Class API prototypes. */ + +#define ux_host_class_asix_entry _ux_host_class_asix_entry +#define ux_host_class_asix_read _ux_host_class_asix_read +#define ux_host_class_asix_write _ux_host_class_asix_write + +#endif diff --git a/common/usbx_host_classes/inc/ux_host_class_audio.h b/common/usbx_host_classes/inc/ux_host_class_audio.h new file mode 100644 index 0000000..c976e2d --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_audio.h @@ -0,0 +1,445 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_audio.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX audio class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_AUDIO_H +#define UX_HOST_CLASS_AUDIO_H + + +/* Define Audio Class main constants. */ + +#define UX_HOST_CLASS_AUDIO_CLASS_TRANSFER_TIMEOUT 30 +#define UX_HOST_CLASS_AUDIO_CLASS 1 +#define UX_HOST_CLASS_AUDIO_SUBCLASS_UNDEFINED 0 +#define UX_HOST_CLASS_AUDIO_SUBCLASS_CONTROL 1 +#define UX_HOST_CLASS_AUDIO_SUBCLASS_STREAMING 2 +#define UX_HOST_CLASS_AUDIO_SUBCLASS_MIDI_STREAMING 3 +#define UX_HOST_CLASS_AUDIO_PROTOCOL_UNDEFINED 0 + + +/* Define Audio Class main descriptor types. */ + +#define UX_HOST_CLASS_AUDIO_CS_UNDEFINED 0x20 +#define UX_HOST_CLASS_AUDIO_CS_DEVICE 0x21 +#define UX_HOST_CLASS_AUDIO_CS_CONFIGURATION 0x22 +#define UX_HOST_CLASS_AUDIO_CS_STRING 0x23 +#define UX_HOST_CLASS_AUDIO_CS_INTERFACE 0x24 +#define UX_HOST_CLASS_AUDIO_CS_ENDPOINT 0x25 + + +/* Define Audio Class specific AC interface descriptor subclasses. */ + +#define UX_HOST_CLASS_AUDIO_CS_AC_UNDEFINED 0x00 +#define UX_HOST_CLASS_AUDIO_CS_HEADER 0x01 +#define UX_HOST_CLASS_AUDIO_CS_INPUT_TERMINAL 0x02 +#define UX_HOST_CLASS_AUDIO_CS_OUTPUT_TERMINAL 0x03 +#define UX_HOST_CLASS_AUDIO_CS_MIXER_UNIT 0x04 +#define UX_HOST_CLASS_AUDIO_CS_SELECTOR_UNIT 0x05 +#define UX_HOST_CLASS_AUDIO_CS_FEATURE_UNIT 0x06 +#define UX_HOST_CLASS_AUDIO_CS_PROCESSING_UNIT 0x07 +#define UX_HOST_CLASS_AUDIO_CS_EXTENSION_UNIT 0x08 + + +/* Define Audio Class specific AS interface descriptor subclasses. */ + +#define UX_HOST_CLASS_AUDIO_CS_AS_UNDEFINED 0x00 +#define UX_HOST_CLASS_AUDIO_CS_AS_GENERAL 0x01 +#define UX_HOST_CLASS_AUDIO_CS_FORMAT_TYPE 0x02 +#define UX_HOST_CLASS_AUDIO_CS_FORMAT_SPECIFIC 0x03 + + +/* Define Audio Class specific processing unit process types. */ + +#define UX_HOST_CLASS_AUDIO_PROCESS_UNDEFINED 0x00 +#define UX_HOST_CLASS_AUDIO_UP_DOWN_MIX_PROCESS 0x01 +#define UX_HOST_CLASS_AUDIO_DOLBY_PROLOGIC_PROCESS 0x02 +#define UX_HOST_CLASS_AUDIO_3D_STEREO_EXTENDED_PROCESS 0x03 +#define UX_HOST_CLASS_AUDIO_REVERBERATION_PROCESS 0x04 +#define UX_HOST_CLASS_AUDIO_CHORUS_PROCESS 0x05 +#define UX_HOST_CLASS_AUDIO_DYN_RANGE_COMP_PROCESS 0x06 + + +/* Define Audio Class specific endpoint descriptor subtypes. */ + +#define UX_HOST_CLASS_AUDIO_DESCRIPTOR_UNDEFINED 0x00 +#define UX_HOST_CLASS_AUDIO_EP_GENERAL 0x01 + + +/* Define Audio Class specific request codes. */ + +#define UX_HOST_CLASS_AUDIO_REQUEST_CODE_UNDEFINED 0x00 +#define UX_HOST_CLASS_AUDIO_SET_CUR 0x01 +#define UX_HOST_CLASS_AUDIO_GET_CUR 0x81 +#define UX_HOST_CLASS_AUDIO_SET_MIN 0x02 +#define UX_HOST_CLASS_AUDIO_GET_MIN 0x82 +#define UX_HOST_CLASS_AUDIO_SET_MAX 0x03 +#define UX_HOST_CLASS_AUDIO_GET_MAX 0x83 +#define UX_HOST_CLASS_AUDIO_SET_RES 0x04 +#define UX_HOST_CLASS_AUDIO_GET_RES 0x84 +#define UX_HOST_CLASS_AUDIO_SET_MEM 0x05 +#define UX_HOST_CLASS_AUDIO_GET_MEM 0x85 +#define UX_HOST_CLASS_AUDIO_GET_STAT 0xFF + + +/* Define Audio Class specific terminal control selectors. */ + +#define UX_HOST_CLASS_AUDIO_TE_CONTROL_UNDEFINED 0x00 +#define UX_HOST_CLASS_AUDIO_COPY_PROTECT_CONTROL 0x01 + + +/* Define Audio Class specific feature unit control selectors. */ + +#define UX_HOST_CLASS_AUDIO_FU_CONTROL_UNDEFINED 0x00 +#define UX_HOST_CLASS_AUDIO_MUTE_CONTROL 0x01 +#define UX_HOST_CLASS_AUDIO_VOLUME_CONTROL 0x02 +#define UX_HOST_CLASS_AUDIO_BASS_CONTROL 0x03 +#define UX_HOST_CLASS_AUDIO_MID_CONTROL 0x04 +#define UX_HOST_CLASS_AUDIO_TREBLE_CONTROL 0x05 +#define UX_HOST_CLASS_AUDIO_GRAPHIC_EQUALIZER_CONTROL 0x06 +#define UX_HOST_CLASS_AUDIO_AUTOMATIC_GAIN_CONTROL 0x07 +#define UX_HOST_CLASS_AUDIO_DELAY_CONTROL 0x08 +#define UX_HOST_CLASS_AUDIO_BASS_BOOST_CONTROL 0x09 +#define UX_HOST_CLASS_AUDIO_LOUNDNESS_CONTROL 0x0A + + +/* Define Audio Class input terminal types. */ + +#define UX_HOST_CLASS_AUDIO_INPUT 0x0200 +#define UX_HOST_CLASS_AUDIO_MICROPHONE 0x0201 +#define UX_HOST_CLASS_AUDIO_DESKTOP_MICROPHONE 0x0202 +#define UX_HOST_CLASS_AUDIO_PERSONAL_MICROPHONE 0x0203 +#define UX_HOST_CLASS_AUDIO_OMNI_DIRECTIONAL_MICROPHONE 0x0204 +#define UX_HOST_CLASS_AUDIO_MICROPHONE_ARRAY 0x0205 +#define UX_HOST_CLASS_AUDIO_PROCESSING_MICROPHONE_ARRAY 0x0206 + + +/* Define Audio Class output terminal types. */ + +#define UX_HOST_CLASS_AUDIO_OUTPUT 0x0300 +#define UX_HOST_CLASS_AUDIO_SPEAKER 0x0301 +#define UX_HOST_CLASS_AUDIO_HEADPHONES 0x0302 +#define UX_HOST_CLASS_AUDIO_HEAD_MOUNTED_DISPLAY 0x0303 +#define UX_HOST_CLASS_AUDIO_DESKTOP_SPEAKER 0x0304 +#define UX_HOST_CLASS_AUDIO_ROOM_SPEAKER 0x0305 +#define UX_HOST_CLASS_AUDIO_COMMUNICATION_SPEAKER 0x0306 +#define UX_HOST_CLASS_AUDIO_LOW_FREQUENCY_SPEAKER 0x0307 + + +/* Define Audio Class bidirectional terminal types. */ + +#define UX_HOST_CLASS_AUDIO_BIDIRECTIONAL_UNDEFINED 0x0400 +#define UX_HOST_CLASS_AUDIO_HANDSET 0x0401 +#define UX_HOST_CLASS_AUDIO_HEADSET 0x0402 +#define UX_HOST_CLASS_AUDIO_SPEAKERPHONE 0x0403 +#define UX_HOST_CLASS_AUDIO_ECHO_SUPRESS_SPEAKERPHONE 0x0404 +#define UX_HOST_CLASS_AUDIO_ECHO_CANCEL_SPEAKERPHONE 0x0405 + + +/* Define Audio Class telephony terminal types. */ + +#define UX_HOST_CLASS_AUDIO_TELEPHONTY_UNDEFINED 0x0400 +#define UX_HOST_CLASS_AUDIO_PHONE_LINE 0x0401 +#define UX_HOST_CLASS_AUDIO_TELEPHONE 0x0402 +#define UX_HOST_CLASS_AUDIO_DOWN_LINE_PHONE 0x0403 + + +/* Define Audio Class encoding format types. */ + +#define UX_HOST_CLASS_AUDIO_FORMAT_TYPE_UNDEFINED 0 +#define UX_HOST_CLASS_AUDIO_FORMAT_TYPE_I 1 +#define UX_HOST_CLASS_AUDIO_FORMAT_TYPE_II 2 +#define UX_HOST_CLASS_AUDIO_FORMAT_TYPE_III 3 + +#define UX_HOST_CLASS_AUDIO_FORMAT_PCM 1 +#define UX_HOST_CLASS_AUDIO_FORMAT_PCM8 2 +#define UX_HOST_CLASS_AUDIO_FORMAT_IEEE_FLOAT 3 +#define UX_HOST_CLASS_AUDIO_FORMAT_ALAW 4 +#define UX_HOST_CLASS_AUDIO_FORMAT_MULAW 5 + +#define UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_ENTRIES 8 +#define UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH 8 + +#define UX_HOST_CLASS_AUDIO_INPUT_TERMINAL_DESCRIPTOR_ENTRIES 10 +#define UX_HOST_CLASS_AUDIO_INPUT_TERMINAL_DESCRIPTOR_LENGTH 12 + +#define UX_HOST_CLASS_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR_ENTRIES 8 +#define UX_HOST_CLASS_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR_LENGTH 9 + +#define UX_HOST_CLASS_AUDIO_FEATURE_UNIT_DESCRIPTOR_ENTRIES 7 +#define UX_HOST_CLASS_AUDIO_FEATURE_UNIT_DESCRIPTOR_LENGTH 7 + +#define UX_HOST_CLASS_AUDIO_STREAMING_INTERFACE_DESCRIPTOR_ENTRIES 6 +#define UX_HOST_CLASS_AUDIO_STREAMING_INTERFACE_DESCRIPTOR_LENGTH 6 + +#define UX_HOST_CLASS_AUDIO_STREAMING_ENDPOINT_DESCRIPTOR_ENTRIES 6 +#define UX_HOST_CLASS_AUDIO_STREAMING_ENDPOINT_DESCRIPTOR_LENGTH 6 + + +/* Define Audio Class specific interface descriptor. */ + +#define UX_HOST_CLASS_AUDIO_MAX_CHANNEL 8 +#define UX_HOST_CLASS_AUDIO_NAME_LENGTH 64 + +typedef struct UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bFormatType; + ULONG bNrChannels; + ULONG bSubframeSize; + ULONG bBitResolution; + ULONG bSamFreqType; +} UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR; + + +/* Define Audio Class specific input terminal interface descriptor. */ + +typedef struct UX_HOST_CLASS_AUDIO_INPUT_TERMINAL_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bTerminalID; + ULONG wTerminalType; + ULONG bAssocTerminal; + ULONG bNrChannels; + ULONG wChannelConfig; + ULONG iChannelNames; + ULONG iTerminal; +} UX_HOST_CLASS_AUDIO_INPUT_TERMINAL_DESCRIPTOR; + + +/* Define Audio Class specific output terminal interface descriptor. */ + +typedef struct UX_HOST_CLASS_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bTerminalID; + ULONG wTerminalType; + ULONG bAssocTerminal; + ULONG bSourceID; + ULONG iTerminal; +} UX_HOST_CLASS_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR; + + +/* Define Audio Class specific feature unit descriptor. */ + +typedef struct UX_HOST_CLASS_AUDIO_FEATURE_UNIT_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bUnitID; + ULONG bSourceID; + ULONG bControlSize; + ULONG bmaControls; +} UX_HOST_CLASS_AUDIO_FEATURE_UNIT_DESCRIPTOR; + + +/* Define Audio Class streaming interface descriptor. */ + +typedef struct UX_HOST_CLASS_AUDIO_STREAMING_INTERFACE_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bTerminalLink; + ULONG bDelay; + ULONG wFormatTag; +} UX_HOST_CLASS_AUDIO_STREAMING_INTERFACE_DESCRIPTOR; + + +/* Define Audio Class specific streaming endpoint descriptor. */ + +typedef struct UX_HOST_CLASS_AUDIO_STREAMING_ENDPOINT_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bmAttributes; + ULONG bLockDelayUnits; + ULONG wLockDelay; +} UX_HOST_CLASS_AUDIO_STREAMING_ENDPOINT_DESCRIPTOR; + + +/* Define Audio Class instance structure. */ + +typedef struct UX_HOST_CLASS_AUDIO_STRUCT +{ + + struct UX_HOST_CLASS_AUDIO_STRUCT + *ux_host_class_audio_next_instance; + UX_HOST_CLASS *ux_host_class_audio_class; + UX_DEVICE *ux_host_class_audio_device; + UX_INTERFACE *ux_host_class_audio_streaming_interface; + ULONG ux_host_class_audio_control_interface_number; + UX_ENDPOINT *ux_host_class_audio_isochronous_endpoint; + struct UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST_STRUCT + *ux_host_class_audio_head_transfer_request; + struct UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST_STRUCT + *ux_host_class_audio_tail_transfer_request; + UINT ux_host_class_audio_state; + ULONG ux_host_class_audio_terminal_link; + ULONG ux_host_class_audio_type; + UCHAR * ux_host_class_audio_configuration_descriptor; + ULONG ux_host_class_audio_configuration_descriptor_length; + ULONG ux_host_class_audio_feature_unit_id; + UINT ux_host_class_audio_channels; + ULONG ux_host_class_audio_channel_control[UX_HOST_CLASS_AUDIO_MAX_CHANNEL]; + UCHAR ux_host_class_audio_name[UX_HOST_CLASS_AUDIO_NAME_LENGTH]; + TX_SEMAPHORE ux_host_class_audio_semaphore; +} UX_HOST_CLASS_AUDIO; + + +/* Define Audio Class isochronous USB transfer request structure. */ + +typedef struct UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST_STRUCT +{ + + ULONG ux_host_class_audio_transfer_request_status; + UCHAR * ux_host_class_audio_transfer_request_data_pointer; + ULONG ux_host_class_audio_transfer_request_requested_length; + ULONG ux_host_class_audio_transfer_request_actual_length; + VOID (*ux_host_class_audio_transfer_request_completion_function) (struct UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST_STRUCT *); + TX_SEMAPHORE ux_host_class_audio_transfer_request_semaphore; + VOID *ux_host_class_audio_transfer_request_class_instance; + UINT ux_host_class_audio_transfer_request_completion_code; + struct UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST_STRUCT + *ux_host_class_audio_transfer_request_next_audio_transfer_request; + UX_TRANSFER ux_host_class_audio_transfer_request; +} UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST; + + +/* Define Audio Class channel/value control structures. */ + +typedef struct UX_HOST_CLASS_AUDIO_CONTROL_STRUCT +{ + + ULONG ux_host_class_audio_control; + ULONG ux_host_class_audio_control_channel; + ULONG ux_host_class_audio_control_min; + ULONG ux_host_class_audio_control_max; + ULONG ux_host_class_audio_control_res; + ULONG ux_host_class_audio_control_cur; +} UX_HOST_CLASS_AUDIO_CONTROL; + + +typedef struct UX_HOST_CLASS_AUDIO_CHANNEL_STRUCT +{ + + ULONG ux_host_class_audio_channel_control; + ULONG ux_host_class_audio_channel; +} UX_HOST_CLASS_AUDIO_CHANNEL; + + +/* Define Audio Class sampling selection structure. */ + +typedef struct UX_HOST_CLASS_AUDIO_SAMPLING_STRUCT +{ + + ULONG ux_host_class_audio_sampling_channels; + ULONG ux_host_class_audio_sampling_frequency; + ULONG ux_host_class_audio_sampling_resolution; +} UX_HOST_CLASS_AUDIO_SAMPLING; + + +/* Define Audio Class sampling characteristics structure. */ + +typedef struct UX_HOST_CLASS_AUDIO_SAMPLING_CHARACTERISTICS_STRUCT +{ + + ULONG ux_host_class_audio_sampling_characteristics_channels; + ULONG ux_host_class_audio_sampling_characteristics_frequency_low; + ULONG ux_host_class_audio_sampling_characteristics_frequency_high; + ULONG ux_host_class_audio_sampling_characteristics_resolution; +} UX_HOST_CLASS_AUDIO_SAMPLING_CHARACTERISTICS; + + +/* Define Audio Class function prototypes. */ + +UINT _ux_host_class_audio_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_audio_alternate_setting_locate(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_SAMPLING *audio_sampling, UINT *alternate_setting); +UINT _ux_host_class_audio_configure(UX_HOST_CLASS_AUDIO *audio); +UINT _ux_host_class_audio_control_get(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_CONTROL *audio_control); +UINT _ux_host_class_audio_control_value_get(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_CONTROL *audio_control); +UINT _ux_host_class_audio_control_value_set(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_CONTROL *audio_control); +UINT _ux_host_class_audio_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_audio_descriptor_get(UX_HOST_CLASS_AUDIO *audio); +UINT _ux_host_class_audio_device_controls_list_get(UX_HOST_CLASS_AUDIO *audio); +UINT _ux_host_class_audio_device_type_get(UX_HOST_CLASS_AUDIO *audio); +UINT _ux_host_class_audio_endpoints_get(UX_HOST_CLASS_AUDIO *audio); +UINT _ux_host_class_audio_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_audio_read(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST *audio_transfer_request); +UINT _ux_host_class_audio_streaming_sampling_get(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_SAMPLING_CHARACTERISTICS *audio_sampling); +UINT _ux_host_class_audio_streaming_sampling_set(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_SAMPLING *audio_sampling); +UINT _ux_host_class_audio_streaming_terminal_get(UX_HOST_CLASS_AUDIO *audio); +UINT _ux_host_class_audio_transfer_request(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST *audio_transfer_request); +VOID _ux_host_class_audio_transfer_request_completed(UX_TRANSFER *transfer_request); +UINT _ux_host_class_audio_write(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST *audio_transfer_request); + +/* Define Asix Class API prototypes. */ + +#define ux_host_class_audio_entry _ux_host_class_audio_entry +#define ux_host_class_audio_control_get _ux_host_class_audio_control_get +#define ux_host_class_audio_control_value_get _ux_host_class_audio_control_value_get +#define ux_host_class_audio_control_value_set _ux_host_class_audio_control_value_set +#define ux_host_class_audio_read _ux_host_class_audio_read +#define ux_host_class_audio_streaming_sampling_get _ux_host_class_audio_streaming_sampling_get +#define ux_host_class_audio_streaming_sampling_set _ux_host_class_audio_streaming_sampling_set +#define ux_host_class_audio_streaming_terminal_get _ux_host_class_audio_streaming_terminal_get +#define ux_host_class_audio_write _ux_host_class_audio_write + +#endif + + diff --git a/common/usbx_host_classes/inc/ux_host_class_cdc_acm.h b/common/usbx_host_classes/inc/ux_host_class_cdc_acm.h new file mode 100644 index 0000000..62ff9f9 --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_cdc_acm.h @@ -0,0 +1,315 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_cdc_acm.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX CDC ACM class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_CDC_ACM_H +#define UX_HOST_CLASS_CDC_ACM_H + +/* Define CDC ACM Class constants. */ + +#define UX_HOST_CLASS_CDC_ACM_DEVICE_INIT_DELAY 1000 +#define UX_HOST_CLASS_CDC_ACM_CLASS_TRANSFER_TIMEOUT 300000 +#define UX_HOST_CLASS_CDC_DATA_CLASS 0x0A +#define UX_HOST_CLASS_CDC_CONTROL_CLASS 0x02 +#define UX_HOST_CLASS_CDC_ACM_SUBCLASS 0X02 +#define UX_HOST_CLASS_CDC_DLC_SUBCLASS 0X01 +#define UX_HOST_CLASS_CDC_ACM_CS_INTERFACE 0x24 + +/* Define CDC ACM Class descriptor subtypes in functional descriptors. */ +#define UX_HOST_CLASS_CDC_ACM_HEADER_DESCRIPTOR 0X00 +#define UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_DESCRIPTOR 0X01 +#define UX_HOST_CLASS_CDC_ACM_ABSTRACT_CONTROL_MGT_DESCRIPTOR 0X02 +#define UX_HOST_CLASS_CDC_ACM_DIRECT_LINE_MGT_DESCRIPTOR 0X03 +#define UX_HOST_CLASS_CDC_ACM_TELEPHONE_RINGER_DESCRIPTOR 0X04 +#define UX_HOST_CLASS_CDC_ACM_REPORT_CAPABILITY_DESCRIPTOR 0X05 +#define UX_HOST_CLASS_CDC_ACM_UNION_DESCRIPTOR 0X06 +#define UX_HOST_CLASS_CDC_ACM_COUNTRY_SELECTION_DESCRIPTOR 0X07 +#define UX_HOST_CLASS_CDC_ACM_TELEPHONE_OPERATIONAL_DESCRIPTOR 0X08 +#define UX_HOST_CLASS_CDC_ACM_USB_TERMINAL_DESCRIPTOR 0X09 + +/* Define CDC ACM Class call management descriptors. */ +#define UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_CAPABILITIES 0x03 +#define UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_DCM 0x01 +#define UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_DCI 0x02 + +/* Define CDC ACM command request values. */ + +#define UX_HOST_CLASS_CDC_ACM_REQ_SEND_ENCAPSULATED_COMMAND 0x00 +#define UX_HOST_CLASS_CDC_ACM_REQ_GET_ENCAPSULATED_COMMAND 0x01 +#define UX_HOST_CLASS_CDC_ACM_REQ_SET_COMM_FEATURE 0x02 +#define UX_HOST_CLASS_CDC_ACM_REQ_GET_COMM_FEATURE 0x03 +#define UX_HOST_CLASS_CDC_ACM_REQ_CLEAR_COMM_FEATURE 0x04 +#define UX_HOST_CLASS_CDC_ACM_REQ_SET_AUX_LINE_STATE 0x10 +#define UX_HOST_CLASS_CDC_ACM_REQ_SET_HOOK_STATE 0x11 +#define UX_HOST_CLASS_CDC_ACM_REQ_PULSE_SETUP 0x12 +#define UX_HOST_CLASS_CDC_ACM_REQ_SEND_PULSE 0x13 +#define UX_HOST_CLASS_CDC_ACM_REQ_SET_PUSLE_TIME 0x14 +#define UX_HOST_CLASS_CDC_ACM_REQ_RING_AUX_JACK 0x15 +#define UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_CODING 0x20 +#define UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_CODING 0x21 +#define UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_STATE 0x22 +#define UX_HOST_CLASS_CDC_ACM_REQ_SEND_BREAK 0x23 +#define UX_HOST_CLASS_CDC_ACM_REQ_SET_RINGER_PARMS 0x30 +#define UX_HOST_CLASS_CDC_ACM_REQ_GET_RINGER_PARMS 0x31 +#define UX_HOST_CLASS_CDC_ACM_REQ_SET_OPERATION_PARMS 0x32 +#define UX_HOST_CLASS_CDC_ACM_REQ_GET_OPERATION_PARMS 0x33 +#define UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_PARMS 0x34 +#define UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_PARMS 0x35 + +/* Define CDC ACM line output control values. */ + +#define UX_HOST_CLASS_CDC_ACM_CTRL_DTR 0x01 +#define UX_HOST_CLASS_CDC_ACM_CTRL_RTS 0x02 + +/* Define CDC ACM line input control values. */ + +#define UX_HOST_CLASS_CDC_ACM_CTRL_DCD 0x01 +#define UX_HOST_CLASS_CDC_ACM_CTRL_DSR 0x02 +#define UX_HOST_CLASS_CDC_ACM_CTRL_BRK 0x04 +#define UX_HOST_CLASS_CDC_ACM_CTRL_RI 0x08 + +#define UX_HOST_CLASS_CDC_ACM_CTRL_FRAMING 0x10 +#define UX_HOST_CLASS_CDC_ACM_CTRL_PARITY 0x20 +#define UX_HOST_CLASS_CDC_ACM_CTRL_OVERRUN 0x40 + +/* Define CDC ACM Class packet equivalences. */ + +#define UX_HOST_CLASS_CDC_ACM_PACKET_SIZE 128 + +/* Define CDC ACM default values. */ + +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_RATE 9600 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_DATA_BIT 8 + +/* Define CDC ACM line coding definitions. */ + +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT_0 0 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT_15 1 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT_2 2 + +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY_NONE 0 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY_ODD 1 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY_EVEN 2 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY_MARK 3 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY_SPACE 4 + +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH 7 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_RATE 0 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT 4 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY 5 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_DATA_BIT 6 + +/* Define CDC ACM line state definitions. */ + +#define UX_HOST_CLASS_CDC_ACM_LINE_STATE_STOP_BIT_0 0 +#define UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT_15 1 + +/* Define CDC ACM IOCTL Functions. */ + +#define UX_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING 0 +#define UX_HOST_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING 1 +#define UX_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE 2 +#define UX_HOST_CLASS_CDC_ACM_IOCTL_SEND_BREAK 3 +#define UX_HOST_CLASS_CDC_ACM_IOCTL_ABORT_IN_PIPE 5 +#define UX_HOST_CLASS_CDC_ACM_IOCTL_ABORT_OUT_PIPE 6 +#define UX_HOST_CLASS_CDC_ACM_IOCTL_NOTIFICATION_CALLBACK 7 +#define UX_HOST_CLASS_CDC_ACM_IOCTL_GET_DEVICE_STATUS 8 + +/* Define CDC ACM Reception States. */ + +#define UX_HOST_CLASS_CDC_ACM_RECEPTION_STATE_STOPPED 0 +#define UX_HOST_CLASS_CDC_ACM_RECEPTION_STATE_STARTED 1 +#define UX_HOST_CLASS_CDC_ACM_RECEPTION_STATE_IN_TRANSFER 2 + +/* Define supported notification types. */ + +#define UX_HOST_CLASS_CDC_ACM_NOTIFICATION_NETWORK_CONNECTION 0x00 +#define UX_HOST_CLASS_CDC_ACM_NOTIFICATION_RESPONSE_AVAILABLE 0x01 +#define UX_HOST_CLASS_CDC_ACM_NOTIFICATION_SERIAL_STATE 0x20 +#define UX_HOST_CLASS_CDC_ACM_NOTIFICATION_CALL_STATE_CHANGE 0x28 +#define UX_HOST_CLASS_CDC_ACM_NOTIFICATION_LINE_STATE_CHANGE 0x29 +#define UX_HOST_CLASS_CDC_ACM_NOTIFICATION_SPEED_CHANGE 0x2A + +/* Define notification packet format. */ + +#define UX_HOST_CLASS_CDC_ACM_NPF_REQUEST_TYPE 0x00 +#define UX_HOST_CLASS_CDC_ACM_NPF_NOTIFICATION_TYPE 0x01 +#define UX_HOST_CLASS_CDC_ACM_NPF_VALUE 0x02 +#define UX_HOST_CLASS_CDC_ACM_NPF_INDEX 0x04 +#define UX_HOST_CLASS_CDC_ACM_NPF_LENGTH 0x06 + +/* Define CDC ACM Class instance structure. */ + +typedef struct UX_HOST_CLASS_CDC_ACM_STRUCT +{ + struct UX_HOST_CLASS_CDC_ACM_STRUCT + *ux_host_class_cdc_acm_next_instance; + UX_HOST_CLASS *ux_host_class_cdc_acm_class; + UX_DEVICE *ux_host_class_cdc_acm_device; + UX_ENDPOINT *ux_host_class_cdc_acm_bulk_in_endpoint; + UX_ENDPOINT *ux_host_class_cdc_acm_bulk_out_endpoint; + UX_ENDPOINT *ux_host_class_cdc_acm_interrupt_endpoint; + UX_INTERFACE *ux_host_class_cdc_acm_interface; + UINT ux_host_class_cdc_acm_instance_status; + UINT ux_host_class_cdc_acm_state; + TX_SEMAPHORE ux_host_class_cdc_acm_semaphore; + ULONG ux_host_class_cdc_acm_notification_count; + UCHAR ux_host_class_cdc_acm_capabilities; + ULONG ux_host_class_cdc_acm_device_state; + struct UX_HOST_CLASS_CDC_ACM_RECEPTION_STRUCT + *ux_host_class_cdc_acm_reception; + + VOID (*ux_host_class_cdc_acm_device_status_change_callback)(struct UX_HOST_CLASS_CDC_ACM_STRUCT *cdc_acm, + ULONG notification_type, ULONG notification_value); +} UX_HOST_CLASS_CDC_ACM; + +/* Define CDC DLC Class instance structure. */ + + +typedef struct UX_HOST_CLASS_CDC_DLC_STRUCT +{ + struct UX_HOST_CLASS_CDC_DLC_STRUCT + *ux_host_class_cdc_dlc_next_instance; + UX_HOST_CLASS *ux_host_class_cdc_dlc_class; + UX_DEVICE *ux_host_class_cdc_dlc_device; + UX_ENDPOINT *ux_host_class_cdc_dlc_bulk_in_endpoint; + UX_ENDPOINT *ux_host_class_cdc_dlc_bulk_out_endpoint; + UX_ENDPOINT *ux_host_class_cdc_dlc_interrupt_endpoint; + UX_INTERFACE *ux_host_class_cdc_dlc_interface; + UINT ux_host_class_cdc_dlc_instance_status; + UINT ux_host_class_cdc_dlc_state; + TX_SEMAPHORE ux_host_class_cdc_dlc_semaphore; + ULONG ux_host_class_cdc_dlc_notification_count; + UCHAR ux_host_class_cdc_dlc_capabilities; + struct UX_HOST_CLASS_CDC_DLC_RECEPTION_STRUCT + *ux_host_class_cdc_dlc_reception; + +} UX_HOST_CLASS_CDC_DLC; + +/* Define CDC ACM reception structure. */ + +typedef struct UX_HOST_CLASS_CDC_ACM_RECEPTION_STRUCT +{ + + ULONG ux_host_class_cdc_acm_reception_state; + ULONG ux_host_class_cdc_acm_reception_block_size; + UCHAR *ux_host_class_cdc_acm_reception_data_buffer; + ULONG ux_host_class_cdc_acm_reception_data_buffer_size; + UCHAR *ux_host_class_cdc_acm_reception_data_head; + UCHAR *ux_host_class_cdc_acm_reception_data_tail; + VOID (*ux_host_class_cdc_acm_reception_callback)(struct UX_HOST_CLASS_CDC_ACM_STRUCT *cdc_acm, + UINT status, + UCHAR *reception_buffer, + ULONG reception_size); + +} UX_HOST_CLASS_CDC_ACM_RECEPTION; + +/* Define CDC ACM Line Coding IOCTL structure. */ + +typedef struct UX_HOST_CLASS_CDC_ACM_LINE_CODING_STRUCT +{ + + ULONG ux_host_class_cdc_acm_line_coding_dter; + ULONG ux_host_class_cdc_acm_line_coding_stop_bit; + ULONG ux_host_class_cdc_acm_line_coding_parity; + ULONG ux_host_class_cdc_acm_line_coding_data_bits; + +} UX_HOST_CLASS_CDC_ACM_LINE_CODING; + +/* Define CDC ACM Line State IOCTL structure. */ + +typedef struct UX_HOST_CLASS_CDC_ACM_LINE_STATE_STRUCT +{ + + ULONG ux_host_class_cdc_acm_line_state_rts; + ULONG ux_host_class_cdc_acm_line_state_dtr; + +} UX_HOST_CLASS_CDC_ACM_LINE_STATE; + +/* Define CDC ACM Line break IOCTL structure. */ + +typedef struct UX_HOST_CLASS_CDC_ACM_LINE_BREAK_STRUCT +{ + + ULONG ux_host_class_cdc_acm_line_break; + +} UX_HOST_CLASS_CDC_ACM_LINE_BREAK; + +/* Define CDC ACM Class function prototypes. */ + +UINT _ux_host_class_cdc_acm_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_cdc_acm_configure(UX_HOST_CLASS_CDC_ACM *cdc_acm); +UINT _ux_host_class_cdc_acm_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_cdc_acm_endpoints_get(UX_HOST_CLASS_CDC_ACM *cdc_acm); +UINT _ux_host_class_cdc_acm_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_cdc_acm_read (UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_cdc_acm_write(UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_cdc_acm_ioctl(UX_HOST_CLASS_CDC_ACM *cdc_acm, ULONG request, + VOID *parameter); +UINT _ux_host_class_cdc_acm_command(UX_HOST_CLASS_CDC_ACM *cdc_acm, ULONG command, + ULONG value, UCHAR *data_buffer, ULONG data_length); +VOID _ux_host_class_cdc_acm_transfer_request_completed(UX_TRANSFER *transfer_request); +UINT _ux_host_class_cdc_acm_capabilities_get(UX_HOST_CLASS_CDC_ACM *cdc_acm); +UINT _ux_host_class_cdc_acm_reception_stop (UX_HOST_CLASS_CDC_ACM *cdc_acm, + UX_HOST_CLASS_CDC_ACM_RECEPTION *cdc_acm_reception); +UINT _ux_host_class_cdc_acm_reception_start (UX_HOST_CLASS_CDC_ACM *cdc_acm, + UX_HOST_CLASS_CDC_ACM_RECEPTION *cdc_acm_reception); + +VOID _ux_host_class_cdc_acm_reception_callback (UX_TRANSFER *transfer_request); + + +/* Define CDC ACM Class API prototypes. */ + +#define ux_host_class_cdc_acm_entry _ux_host_class_cdc_acm_entry +#define ux_host_class_cdc_acm_read _ux_host_class_cdc_acm_read +#define ux_host_class_cdc_acm_write _ux_host_class_cdc_acm_write +#define ux_host_class_cdc_acm_ioctl _ux_host_class_cdc_acm_ioctl +#define ux_host_class_cdc_acm_reception_start _ux_host_class_cdc_acm_reception_start +#define ux_host_class_cdc_acm_reception_stop _ux_host_class_cdc_acm_reception_stop + + +#endif diff --git a/common/usbx_host_classes/inc/ux_host_class_cdc_ecm.h b/common/usbx_host_classes/inc/ux_host_class_cdc_ecm.h new file mode 100644 index 0000000..a3f15d1 --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_cdc_ecm.h @@ -0,0 +1,289 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_cdc_ecm.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX CDC_ECM class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_CDC_ECM_H +#define UX_HOST_CLASS_CDC_ECM_H + +/* Include the NetX API. */ +#include "nx_api.h" +#include "ux_network_driver.h" + +/* Define CDC_ECM Class constants. Insert here the PID/VID of vendors and products using the CDC ECM chipset. + It is a better mechanism to put this value in the ux_user.h file. */ +#ifndef UX_HOST_CLASS_CDC_ECM_VENDOR_ID +#define UX_HOST_CLASS_CDC_ECM_VENDOR_ID 0x0770 +#define UX_HOST_CLASS_CDC_ECM_PRODUCT_ID 0x1042 +#endif + +/* Define CDC_ECM Class/subclass/protocol constants. */ +#define UX_HOST_CLASS_CDC_CONTROL_CLASS 0x02 +#define UX_HOST_CLASS_CDC_DATA_CLASS 0x0A +#define UX_HOST_CLASS_CDC_ECM_CONTROL_SUBCLASS 0x06 +#define UX_HOST_CLASS_CDC_ECM_CONTROL_PROTOCOL 0x00 +#define UX_HOST_CLASS_CDC_ECM_CS_INTERFACE 0x24 +#define UX_HOST_CLASS_CDC_ECM_FUNCTIONAL_DESCRIPTOR 0x0F +#define UX_HOST_CLASS_CDC_ECM_MAC_ADDRESS_STRING_LENGTH 32 +#define UX_HOST_CLASS_CDC_ECM_MAC_ADDRESS_ASCII_LENGTH 8 + +#define UX_HOST_CLASS_CDC_ECM_SPEED_SELECTED_100MPBS 0x100 +#define UX_HOST_CLASS_CDC_ECM_SPEED_SELECTED_10MPBS 0x10 +#define UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN 0 +#define UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP 1 +#define UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_UP 2 +#define UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_DOWN 3 +#define UX_HOST_CLASS_CDC_ECM_BASE_IP_ADDRESS 0xC0A80001 +#define UX_HOST_CLASS_CDC_ECM_BASE_IP_MASK 0xFFFFFF00 +#define UX_HOST_CLASS_CDC_ECM_MAX_MTU 1518 +#define UX_HOST_CLASS_CDC_ECM_ETHERNET_IP 0x0800 +#define UX_HOST_CLASS_CDC_ECM_ETHERNET_ARP 0x0806 +#define UX_HOST_CLASS_CDC_ECM_ETHERNET_RARP 0x8035 +#define UX_HOST_CLASS_CDC_ECM_ETHERNET_PACKET_SIZE 1536 +#define UX_HOST_CLASS_CDC_ECM_NX_ALIGN_PADDING 2 +#ifndef UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES +#define UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES 16 +#endif + +#define UX_HOST_CLASS_CDC_ECM_NX_PACKET_SIZE sizeof(NX_PACKET) + +#define UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE_ASSERT UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG(UX_HOST_CLASS_CDC_ECM_ETHERNET_PACKET_SIZE, UX_HOST_CLASS_CDC_ECM_NX_ALIGN_PADDING), UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE_calc_ovf) +#define UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE (UX_HOST_CLASS_CDC_ECM_ETHERNET_PACKET_SIZE + UX_HOST_CLASS_CDC_ECM_NX_ALIGN_PADDING) + +#define UX_HOST_CLASS_CDC_ECM_NX_BUFF_SIZE_ASSERT \ + UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE_ASSERT \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG( \ + UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE, \ + UX_HOST_CLASS_CDC_ECM_NX_PACKET_SIZE), \ + UX_HOST_CLASS_CDC_ECM_NX_BUFF_SIZE_calc_ovf) +#define UX_HOST_CLASS_CDC_ECM_NX_BUFF_SIZE (UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE + UX_HOST_CLASS_CDC_ECM_NX_PACKET_SIZE) + +#define UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT \ + UX_HOST_CLASS_CDC_ECM_NX_BUFF_SIZE_ASSERT \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG( \ + UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES, \ + UX_HOST_CLASS_CDC_ECM_NX_BUFF_SIZE), \ + UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_calc1_ovf) \ + UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_ADD_ULONG( \ + UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES * \ + UX_HOST_CLASS_CDC_ECM_NX_BUFF_SIZE, \ + 32), UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_calc2_ovf) +#define UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE (UX_HOST_CLASS_CDC_ECM_NX_PKPOOL_ENTRIES * UX_HOST_CLASS_CDC_ECM_NX_BUFF_SIZE + 32) + +#define UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE 14 + +#define UX_HOST_CLASS_CDC_ECM_DEVICE_INIT_DELAY (1 * UX_PERIODIC_RATE) +#define UX_HOST_CLASS_CDC_ECM_CLASS_TRANSFER_TIMEOUT 300000 +#define UX_HOST_CLASS_CDC_ECM_SETUP_BUFFER_SIZE 16 + +/* Define NetX errors inside the CDC ECM class. */ +#define UX_HOST_CLASS_CDC_ECM_NX_SUCCESS 0x00 +#define UX_HOST_CLASS_CDC_ECM_NX_NO_PACKET 0x01 +#define UX_HOST_CLASS_CDC_ECM_NX_UNDERFLOW 0x02 +#define UX_HOST_CLASS_CDC_ECM_NX_OVERFLOW 0x03 +#define UX_HOST_CLASS_CDC_ECM_NX_NO_MAPPING 0x04 +#define UX_HOST_CLASS_CDC_ECM_NX_DELETED 0x05 +#define UX_HOST_CLASS_CDC_ECM_NX_POOL_ERROR 0x06 +#define UX_HOST_CLASS_CDC_ECM_NX_PTR_ERROR 0x07 +#define UX_HOST_CLASS_CDC_ECM_NX_WAIT_ERROR 0x08 +#define UX_HOST_CLASS_CDC_ECM_NX_SIZE_ERROR 0x09 +#define UX_HOST_CLASS_CDC_ECM_NX_OPTION_ERROR 0x0a +#define UX_HOST_CLASS_CDC_ECM_NX_DELETE_ERROR 0x10 +#define UX_HOST_CLASS_CDC_ECM_NX_CALLER_ERROR 0x11 +#define UX_HOST_CLASS_CDC_ECM_NX_INVALID_PACKET 0x12 +#define UX_HOST_CLASS_CDC_ECM_NX_INVALID_SOCKET 0x13 +#define UX_HOST_CLASS_CDC_ECM_NX_NOT_ENABLED 0x14 +#define UX_HOST_CLASS_CDC_ECM_NX_ALREADY_ENABLED 0x15 +#define UX_HOST_CLASS_CDC_ECM_NX_ENTRY_NOT_FOUND 0x16 +#define UX_HOST_CLASS_CDC_ECM_NX_NO_MORE_ENTRIES 0x17 +#define UX_HOST_CLASS_CDC_ECM_NX_ARP_TIMER_ERROR 0x18 +#define UX_HOST_CLASS_CDC_ECM_NX_RESERVED_CODE0 0x19 +#define UX_HOST_CLASS_CDC_ECM_NX_WAIT_ABORTED 0x1A +#define UX_HOST_CLASS_CDC_ECM_NX_IP_INTERNAL_ERROR 0x20 +#define UX_HOST_CLASS_CDC_ECM_NX_IP_ADDRESS_ERROR 0x21 +#define UX_HOST_CLASS_CDC_ECM_NX_ALREADY_BOUND 0x22 +#define UX_HOST_CLASS_CDC_ECM_NX_PORT_UNAVAILABLE 0x23 +#define UX_HOST_CLASS_CDC_ECM_NX_NOT_BOUND 0x24 +#define UX_HOST_CLASS_CDC_ECM_NX_RESERVED_CODE1 0x25 +#define UX_HOST_CLASS_CDC_ECM_NX_SOCKET_UNBOUND 0x26 +#define UX_HOST_CLASS_CDC_ECM_NX_NOT_CREATED 0x27 +#define UX_HOST_CLASS_CDC_ECM_NX_SOCKETS_BOUND 0x28 +#define UX_HOST_CLASS_CDC_ECM_NX_NO_RESPONSE 0x29 +#define UX_HOST_CLASS_CDC_ECM_NX_POOL_DELETED 0x30 +#define UX_HOST_CLASS_CDC_ECM_NX_ALREADY_RELEASED 0x31 +#define UX_HOST_CLASS_CDC_ECM_NX_RESERVED_CODE2 0x32 +#define UX_HOST_CLASS_CDC_ECM_NX_MAX_LISTEN 0x33 +#define UX_HOST_CLASS_CDC_ECM_NX_DUPLICATE_LISTEN 0x34 +#define UX_HOST_CLASS_CDC_ECM_NX_NOT_CLOSED 0x35 +#define UX_HOST_CLASS_CDC_ECM_NX_NOT_LISTEN_STATE 0x36 +#define UX_HOST_CLASS_CDC_ECM_NX_IN_PROGRESS 0x37 +#define UX_HOST_CLASS_CDC_ECM_NX_NOT_CONNECTED 0x38 +#define UX_HOST_CLASS_CDC_ECM_NX_WINDOW_OVERFLOW 0x39 +#define UX_HOST_CLASS_CDC_ECM_NX_ALREADY_SUSPENDED 0x40 +#define UX_HOST_CLASS_CDC_ECM_NX_DISCONNECT_FAILED 0x41 +#define UX_HOST_CLASS_CDC_ECM_NX_STILL_BOUND 0x42 +#define UX_HOST_CLASS_CDC_ECM_NX_NOT_SUCCESSFUL 0x43 +#define UX_HOST_CLASS_CDC_ECM_NX_UNHANDLED_COMMAND 0x44 +#define UX_HOST_CLASS_CDC_ECM_NX_NO_FREE_PORTS 0x45 +#define UX_HOST_CLASS_CDC_ECM_NX_INVALID_PORT 0x46 +#define UX_HOST_CLASS_CDC_ECM_NX_INVALID_RELISTEN 0x47 +#define UX_HOST_CLASS_CDC_ECM_NX_CONNECTION_PENDING 0x48 +#define UX_HOST_CLASS_CDC_ECM_NX_TX_QUEUE_DEPTH 0x49 +#define UX_HOST_CLASS_CDC_ECM_NX_NOT_IMPLEMENTED 0x80 + +/* Define CDC_ECM Class packet equivalences. */ + +#define UX_HOST_CLASS_CDC_ECM_PACKET_SIZE 128 +#define UX_HOST_CLASS_CDC_ECM_NODE_ID_LENGTH 6 + +/* Define supported notification types. */ + +#define UX_HOST_CLASS_CDC_ECM_NOTIFICATION_NETWORK_CONNECTION 0x00 +#define UX_HOST_CLASS_CDC_ECM_NOTIFICATION_RESPONSE_AVAILABLE 0x01 +#define UX_HOST_CLASS_CDC_ECM_NOTIFICATION_SERIAL_STATE 0x20 +#define UX_HOST_CLASS_CDC_ECM_NOTIFICATION_CALL_STATE_CHANGE 0x28 +#define UX_HOST_CLASS_CDC_ECM_NOTIFICATION_LINE_STATE_CHANGE 0x29 +#define UX_HOST_CLASS_CDC_ECM_NOTIFICATION_SPEED_CHANGE 0x2A + +/* Define notification packet format. */ + +#define UX_HOST_CLASS_CDC_ECM_NPF_REQUEST_TYPE 0x00 +#define UX_HOST_CLASS_CDC_ECM_NPF_NOTIFICATION_TYPE 0x01 +#define UX_HOST_CLASS_CDC_ECM_NPF_VALUE 0x02 +#define UX_HOST_CLASS_CDC_ECM_NPF_INDEX 0x04 +#define UX_HOST_CLASS_CDC_ECM_NPF_LENGTH 0x06 + +/* Define supported notification values. */ + +#define UX_HOST_CLASS_CDC_ECM_NOTIFICATION_NETWORK_LINK_DOWN 0x00 +#define UX_HOST_CLASS_CDC_ECM_NOTIFICATION_NETWORK_LINK_UP 0x01 + +/* Define packet allocation timeout in milliseconds. */ + +#ifndef UX_HOST_CLASS_CDC_ECM_PACKET_POOL_WAIT +#define UX_HOST_CLASS_CDC_ECM_PACKET_POOL_WAIT 1000 +#endif + +/* Define CDC_ECM Class instance structure. */ + +typedef struct UX_HOST_CLASS_CDC_ECM_STRUCT +{ + struct UX_HOST_CLASS_CDC_ECM_STRUCT + *ux_host_class_cdc_ecm_next_instance; + UX_HOST_CLASS *ux_host_class_cdc_ecm_class; + UX_DEVICE *ux_host_class_cdc_ecm_device; + UX_ENDPOINT *ux_host_class_cdc_ecm_bulk_in_endpoint; + UX_ENDPOINT *ux_host_class_cdc_ecm_bulk_out_endpoint; + UX_ENDPOINT *ux_host_class_cdc_ecm_interrupt_endpoint; + UX_INTERFACE *ux_host_class_cdc_ecm_interface_data; + UX_INTERFACE *ux_host_class_cdc_ecm_interface_control; + UCHAR ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process; + UCHAR ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish; + TX_SEMAPHORE ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore; + UCHAR ux_host_class_cdc_ecm_bulk_out_transfer_check_and_arm_in_process; + UCHAR ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish; + TX_SEMAPHORE ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore; + UINT ux_host_class_cdc_ecm_instance_status; + UINT ux_host_class_cdc_ecm_state; + TX_SEMAPHORE ux_host_class_cdc_ecm_interrupt_notification_semaphore; + TX_THREAD ux_host_class_cdc_ecm_thread; + UCHAR *ux_host_class_cdc_ecm_thread_stack; + ULONG ux_host_class_cdc_ecm_notification_count; + ULONG ux_host_class_cdc_ecm_primary_phy_id; + ULONG ux_host_class_cdc_ecm_primary_phy_type; + ULONG ux_host_class_cdc_ecm_secondary_phy_id; + ULONG ux_host_class_cdc_ecm_secondary_phy_type; + ULONG ux_host_class_cdc_ecm_model_revision_number; + ULONG ux_host_class_cdc_ecm_vendor_model_number; + ULONG ux_host_class_cdc_ecm_speed_selected; + ULONG ux_host_class_cdc_ecm_device_state; + ULONG ux_host_class_cdc_ecm_link_state; + NX_PACKET *ux_host_class_cdc_ecm_xmit_queue_head; + NX_PACKET *ux_host_class_cdc_ecm_xmit_queue_tail; + NX_PACKET_POOL ux_host_class_cdc_ecm_packet_pool; + UCHAR *ux_host_class_cdc_ecm_pool_memory; + UCHAR ux_host_class_cdc_ecm_node_id[UX_HOST_CLASS_CDC_ECM_NODE_ID_LENGTH]; + VOID (*ux_host_class_cdc_ecm_device_status_change_callback)(struct UX_HOST_CLASS_CDC_ECM_STRUCT *cdc_ecm, + ULONG device_state); + VOID *ux_host_class_cdc_ecm_network_handle; + +} UX_HOST_CLASS_CDC_ECM; + + +/* Define ECM Interface Functional descriptor. */ + +#define UX_HOST_CLASS_CDC_ECM_INTERFACE_DESCRIPTOR_ENTRIES 8 +#define UX_HOST_CLASS_CDC_ECM_INTERFACE_DESCRIPTOR_LENGTH 13 + +typedef struct UX_HOST_CLASS_ECM_INTERFACE_DESCRIPTOR_STRUCT +{ + ULONG bFunctionLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG iMACAddress; + ULONG bmEthernetStatistics; + ULONG wMaxSegmentSize; + ULONG wNumberMCFilters; + ULONG bNumberPowerFilters; +} UX_HOST_CLASS_ECM_INTERFACE_DESCRIPTOR; + +/* Define CDC ECM Class function prototypes. */ + +UINT _ux_host_class_cdc_ecm_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_cdc_ecm_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_cdc_ecm_endpoints_get(UX_HOST_CLASS_CDC_ECM *cdc_ecm); +UINT _ux_host_class_cdc_ecm_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_cdc_ecm_write(VOID *cdc_ecm_class, NX_PACKET *packet); +VOID _ux_host_class_cdc_ecm_interrupt_notification(UX_TRANSFER *transfer_request); +VOID _ux_host_class_cdc_ecm_thread(ULONG parameter); +VOID _ux_host_class_cdc_ecm_transmission_callback(UX_TRANSFER *transfer_request); +VOID _ux_host_class_cdc_ecm_transmit_queue_clean(UX_HOST_CLASS_CDC_ECM *cdc_ecm_control); +UINT _ux_host_class_cdc_ecm_mac_address_get(UX_HOST_CLASS_CDC_ECM *cdc_ecm); + +/* Define CDC ECM Class API prototypes. */ + +#define ux_host_class_cdc_ecm_entry _ux_host_class_cdc_ecm_entry +#define ux_host_class_cdc_ecm_write _ux_host_class_cdc_ecm_write + +#endif diff --git a/common/usbx_host_classes/inc/ux_host_class_gser.h b/common/usbx_host_classes/inc/ux_host_class_gser.h new file mode 100644 index 0000000..a9d76b6 --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_gser.h @@ -0,0 +1,261 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_gser.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX Generic Serial Class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_GSER_H +#define UX_HOST_CLASS_GSER_H + + +/* Define Sierra Wireless AR Class constants. */ + +#define UX_HOST_CLASS_GSER_CLASS_TRANSFER_TIMEOUT 300000 +#ifndef UX_HOST_CLASS_GSER_VENDOR_ID +#define UX_HOST_CLASS_GSER_VENDOR_ID 0X05C6 +#define UX_HOST_CLASS_GSER_PRODUCT_ID 0X9002 +#endif + +/* Define serial interfaces equivalences. */ +#define UX_HOST_CLASS_GSER_INTERFACE_NUMBER 3 + +/* Define packet equivalences. */ +#define UX_HOST_CLASS_GSER_PACKET_SIZE 128 + +/* Define Generic AR IOCTL functions. */ + +#define UX_HOST_CLASS_GSER_REQ_SEND_ENCAPSULATED_COMMAND 0x00 +#define UX_HOST_CLASS_GSER_REQ_GET_ENCAPSULATED_COMMAND 0x01 +#define UX_HOST_CLASS_GSER_REQ_SET_COMM_FEATURE 0x02 +#define UX_HOST_CLASS_GSER_REQ_GET_COMM_FEATURE 0x03 +#define UX_HOST_CLASS_GSER_REQ_CLEAR_COMM_FEATURE 0x04 +#define UX_HOST_CLASS_GSER_REQ_SET_AUX_LINE_STATE 0x10 +#define UX_HOST_CLASS_GSER_REQ_SET_HOOK_STATE 0x11 +#define UX_HOST_CLASS_GSER_REQ_PULSE_SETUP 0x12 +#define UX_HOST_CLASS_GSER_REQ_SEND_PULSE 0x13 +#define UX_HOST_CLASS_GSER_REQ_SET_PUSLE_TIME 0x14 +#define UX_HOST_CLASS_GSER_REQ_RING_AUX_JACK 0x15 +#define UX_HOST_CLASS_GSER_REQ_SET_LINE_CODING 0x20 +#define UX_HOST_CLASS_GSER_REQ_GET_LINE_CODING 0x21 +#define UX_HOST_CLASS_GSER_REQ_SET_LINE_STATE 0x22 +#define UX_HOST_CLASS_GSER_REQ_SEND_BREAK 0x23 +#define UX_HOST_CLASS_GSER_REQ_SET_RINGER_PARMS 0x30 +#define UX_HOST_CLASS_GSER_REQ_GET_RINGER_PARMS 0x31 +#define UX_HOST_CLASS_GSER_REQ_SET_OPERATION_PARMS 0x32 +#define UX_HOST_CLASS_GSER_REQ_GET_OPERATION_PARMS 0x33 +#define UX_HOST_CLASS_GSER_REQ_SET_LINE_PARMS 0x34 +#define UX_HOST_CLASS_GSER_REQ_GET_LINE_PARMS 0x35 + +/* Define CDC ACM line output control values. */ + +#define UX_HOST_CLASS_GSER_CTRL_DTR 0x01 +#define UX_HOST_CLASS_GSER_CTRL_RTS 0x02 + +/* Define CDC ACM line input control values. */ + +#define UX_HOST_CLASS_GSER_CTRL_DCD 0x01 +#define UX_HOST_CLASS_GSER_CTRL_DSR 0x02 +#define UX_HOST_CLASS_GSER_CTRL_BRK 0x04 +#define UX_HOST_CLASS_GSER_CTRL_RI 0x08 + +#define UX_HOST_CLASS_GSER_CTRL_FRAMING 0x10 +#define UX_HOST_CLASS_GSER_CTRL_PARITY 0x20 +#define UX_HOST_CLASS_GSER_CTRL_OVERRUN 0x40 + +/* Define CDC ACM default values. */ + +#define UX_HOST_CLASS_GSER_LINE_CODING_DEFAULT_RATE 9600 +#define UX_HOST_CLASS_GSER_LINE_CODING_DEFAULT_DATA_BIT 8 + +/* Define CDC ACM line coding definitions. */ + +#define UX_HOST_CLASS_GSER_LINE_CODING_STOP_BIT_0 0 +#define UX_HOST_CLASS_GSER_LINE_CODING_STOP_BIT_15 1 +#define UX_HOST_CLASS_GSER_LINE_CODING_STOP_BIT_2 2 + +#define UX_HOST_CLASS_GSER_LINE_CODING_PARITY_NONE 0 +#define UX_HOST_CLASS_GSER_LINE_CODING_PARITY_ODD 1 +#define UX_HOST_CLASS_GSER_LINE_CODING_PARITY_EVEN 2 +#define UX_HOST_CLASS_GSER_LINE_CODING_PARITY_MARK 3 +#define UX_HOST_CLASS_GSER_LINE_CODING_PARITY_SPACE 4 + +#define UX_HOST_CLASS_GSER_LINE_CODING_LENGTH 7 +#define UX_HOST_CLASS_GSER_LINE_CODING_RATE 0 +#define UX_HOST_CLASS_GSER_LINE_CODING_STOP_BIT 4 +#define UX_HOST_CLASS_GSER_LINE_CODING_PARITY 5 +#define UX_HOST_CLASS_GSER_LINE_CODING_DATA_BIT 6 + +/* Define CDC ACM line state definitions. */ + +#define UX_HOST_CLASS_GSER_LINE_STATE_STOP_BIT_0 0 +#define UX_HOST_CLASS_GSER_LINE_CODING_STOP_BIT_15 1 + +/* Define CDC ACM IOCTL Functions. */ + +#define UX_HOST_CLASS_GSER_IOCTL_SET_LINE_CODING 0 +#define UX_HOST_CLASS_GSER_IOCTL_GET_LINE_CODING 1 +#define UX_HOST_CLASS_GSER_IOCTL_SET_LINE_STATE 2 +#define UX_HOST_CLASS_GSER_IOCTL_SEND_BREAK 3 +#define UX_HOST_CLASS_GSER_IOCTL_ABORT_IN_PIPE 5 +#define UX_HOST_CLASS_GSER_IOCTL_ABORT_OUT_PIPE 6 +#define UX_HOST_CLASS_GSER_IOCTL_NOTIFICATION_CALLBACK 7 +#define UX_HOST_CLASS_GSER_IOCTL_GET_DEVICE_STATUS 8 + +/* Define Reception States. */ + +#define UX_HOST_CLASS_GSER_RECEPTION_STATE_STOPPED 0 +#define UX_HOST_CLASS_GSER_RECEPTION_STATE_STARTED 1 +#define UX_HOST_CLASS_GSER_RECEPTION_STATE_IN_TRANSFER 2 + +/* Define the interface structures. */ + +typedef struct UX_HOST_CLASS_GSER_INTERFACE_STRUCT +{ + + UX_INTERFACE *ux_host_class_gser_interface; + UX_ENDPOINT *ux_host_class_gser_bulk_out_endpoint; + UX_ENDPOINT *ux_host_class_gser_bulk_in_endpoint; + TX_SEMAPHORE ux_host_class_gser_semaphore; + struct UX_HOST_CLASS_GSER_RECEPTION_STRUCT *ux_host_class_gser_reception; + ULONG ux_host_class_gser_notification_count; +} UX_HOST_CLASS_GSER_INTERFACE; + +/* Define Generic Serial Class instance structure. */ + +typedef struct UX_HOST_CLASS_GSER_STRUCT +{ + + struct UX_HOST_CLASS_GSER_STRUCT *ux_host_class_gser_next_instance; + UX_HOST_CLASS *ux_host_class_gser_class; + UX_DEVICE *ux_host_class_gser_device; + UINT ux_host_class_gser_state; + struct UX_HOST_CLASS_GSER_INTERFACE_STRUCT ux_host_class_gser_interface_array[UX_HOST_CLASS_GSER_INTERFACE_NUMBER]; + ULONG ux_host_class_gser_device_state; + VOID (*ux_host_class_gser_device_status_change_callback)(struct UX_HOST_CLASS_GSER_STRUCT *gser, + ULONG notification_type, ULONG notification_value); +} UX_HOST_CLASS_GSER; + +/* Define generic serial class reception structure. */ + + +typedef struct UX_HOST_CLASS_GSER_RECEPTION_STRUCT +{ + + ULONG ux_host_class_gser_reception_interface_index; + ULONG ux_host_class_gser_reception_state; + ULONG ux_host_class_gser_reception_block_size; + UCHAR *ux_host_class_gser_reception_data_buffer; + ULONG ux_host_class_gser_reception_data_buffer_size; + UCHAR *ux_host_class_gser_reception_data_head; + UCHAR *ux_host_class_gser_reception_data_tail; + VOID (*ux_host_class_gser_reception_callback)(struct UX_HOST_CLASS_GSER_STRUCT *gser, + UINT status, + UCHAR *reception_buffer, + ULONG reception_size); + +} UX_HOST_CLASS_GSER_RECEPTION; + + +/* Define GSER Line Coding IOCTL structure. */ + +typedef struct UX_HOST_CLASS_GSER_LINE_CODING_STRUCT +{ + + ULONG ux_host_class_gser_line_coding_dter; + ULONG ux_host_class_gser_line_coding_stop_bit; + ULONG ux_host_class_gser_line_coding_parity; + ULONG ux_host_class_gser_line_coding_data_bits; + +} UX_HOST_CLASS_GSER_LINE_CODING; + +/* Define GSER Line State IOCTL structure. */ + +typedef struct UX_HOST_CLASS_GSER_LINE_STATE_STRUCT +{ + + ULONG ux_host_class_gser_line_state_rts; + ULONG ux_host_class_gser_line_state_dtr; + +} UX_HOST_CLASS_GSER_LINE_STATE; + +/* Define GSER Line break IOCTL structure. */ + +typedef struct UX_HOST_CLASS_GSER_LINE_BREAK_STRUCT +{ + + ULONG ux_host_class_gser_line_break; + +} UX_HOST_CLASS_GSER_LINE_BREAK; + + +/* Define GSER Class function prototypes. */ + +UINT _ux_host_class_gser_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_gser_configure(UX_HOST_CLASS_GSER *gser); +UINT _ux_host_class_gser_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_gser_endpoints_get(UX_HOST_CLASS_GSER *gser); +UINT _ux_host_class_gser_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_gser_read (UX_HOST_CLASS_GSER *gser, ULONG interface_index,UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_gser_write(UX_HOST_CLASS_GSER *gser, ULONG interface_index,UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_gser_command(UX_HOST_CLASS_GSER *gser, ULONG interface_index, ULONG command, + ULONG value, UCHAR *data_buffer, ULONG data_length); +UINT _ux_host_class_gser_ioctl(UX_HOST_CLASS_GSER *gser, ULONG interface_index, ULONG ioctl_function, + VOID *parameter); +VOID _ux_host_class_gser_reception_callback (UX_TRANSFER *transfer_request); +UINT _ux_host_class_gser_reception_stop (UX_HOST_CLASS_GSER *gser, + UX_HOST_CLASS_GSER_RECEPTION *gser_reception); +UINT _ux_host_class_gser_reception_start (UX_HOST_CLASS_GSER *gser, + UX_HOST_CLASS_GSER_RECEPTION *gser_reception); + +/* Define GSER Class API prototypes. */ + +#define ux_host_class_gser_entry _ux_host_class_gser_entry +#define ux_host_class_gser_read _ux_host_class_gser_read +#define ux_host_class_gser_write _ux_host_class_gser_write +#define ux_host_class_gser_ioctl _ux_host_class_gser_ioctl +#define ux_host_class_gser_reception_start _ux_host_class_gser_reception_start +#define ux_host_class_gser_reception_stop _ux_host_class_gser_reception_stop + +#endif diff --git a/common/usbx_host_classes/inc/ux_host_class_hid.h b/common/usbx_host_classes/inc/ux_host_class_hid.h new file mode 100644 index 0000000..acce24e --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_hid.h @@ -0,0 +1,1030 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_hid.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX HID class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_HID_H +#define UX_HOST_CLASS_HID_H + + +/* Define HID Class constants. */ + +#define UX_HOST_CLASS_HID_CLASS 3 +#define UX_HOST_CLASS_HID_FIELDS 16 +#define UX_HOST_CLASS_HID_MAX_COLLECTION 4 +#define UX_HOST_CLASS_HID_MAX_REPORT 8 +#define UX_HOST_CLASS_HID_REPORT_SIZE 32 +#define UX_HOST_CLASS_HID_DESCRIPTOR 0x21 +#define UX_HOST_CLASS_HID_ITEM_LENGTH_MASK 3 +#define UX_HOST_CLASS_HID_ITEM_TAG_MASK 0xf0 +#define UX_HOST_CLASS_HID_ITEM_TAG_SHORT 1 +#define UX_HOST_CLASS_HID_ITEM_TAG_LONG 0xf0 +#define UX_HOST_CLASS_HID_MAX_CLIENTS 8 +#define UX_HOST_CLASS_HID_MAX_CLIENT_NAME_LENGTH 63 /* Exclude string null-terminator */ + +#ifndef UX_HOST_CLASS_HID_DECOMPRESSION_BUFFER +#define UX_HOST_CLASS_HID_DECOMPRESSION_BUFFER 4096 +#endif +#define UX_HOST_CLASS_HID_REPORT_DECOMPRESSED 0 +#define UX_HOST_CLASS_HID_REPORT_RAW 1 +#define UX_HOST_CLASS_HID_REPORT_INDIVIDUAL_USAGE 2 +#define UX_HOST_CLASS_HID_INTERRUPT_ENDPOINT_READY 1 +#define UX_HOST_CLASS_HID_INTERRUPT_ENDPOINT_ACTIVE 2 + + +/* Define HID Class item types. */ + +#define UX_HOST_CLASS_HID_TYPE_MAIN 0x0 +#define UX_HOST_CLASS_HID_TYPE_GLOBAL 0x1 +#define UX_HOST_CLASS_HID_TYPE_LOCAL 0x2 +#define UX_HOST_CLASS_HID_TYPE_RESERVED 0x3 + + +/* Define HID Class main tags. */ + +#define UX_HOST_CLASS_HID_MAIN_TAG_INPUT 0x8 +#define UX_HOST_CLASS_HID_MAIN_TAG_OUTPUT 0x9 +#define UX_HOST_CLASS_HID_MAIN_TAG_FEATURE 0xb +#define UX_HOST_CLASS_HID_MAIN_TAG_COLLECTION 0xa +#define UX_HOST_CLASS_HID_MAIN_TAG_END_COLLECTION 0xc + + +/* Define HID Class global tags. */ + +#define UX_HOST_CLASS_HID_GLOBAL_TAG_USAGE_PAGE 0x0 +#define UX_HOST_CLASS_HID_GLOBAL_TAG_LOGICAL_MINIMUM 0x1 +#define UX_HOST_CLASS_HID_GLOBAL_TAG_LOGICAL_MAXIMUM 0x2 +#define UX_HOST_CLASS_HID_GLOBAL_TAG_PHYSICAL_MINIMUM 0x3 +#define UX_HOST_CLASS_HID_GLOBAL_TAG_PHYSICAL_MAXIMUM 0x4 +#define UX_HOST_CLASS_HID_GLOBAL_TAG_UNIT_EXPONENT 0x5 +#define UX_HOST_CLASS_HID_GLOBAL_TAG_UNIT 0x6 +#define UX_HOST_CLASS_HID_GLOBAL_TAG_REPORT_SIZE 0x7 +#define UX_HOST_CLASS_HID_GLOBAL_TAG_REPORT_ID 0x8 +#define UX_HOST_CLASS_HID_GLOBAL_TAG_REPORT_COUNT 0x9 +#define UX_HOST_CLASS_HID_GLOBAL_TAG_PUSH 0xa +#define UX_HOST_CLASS_HID_GLOBAL_TAG_POP 0xb + + +/* Define HID Class local tags. */ + +#define UX_HOST_CLASS_HID_LOCAL_TAG_USAGE 0x0 +#define UX_HOST_CLASS_HID_LOCAL_TAG_USAGE_MINIMUM 0x1 +#define UX_HOST_CLASS_HID_LOCAL_TAG_USAGE_MAXIMUM 0x2 +#define UX_HOST_CLASS_HID_LOCAL_TAG_DESIGNATOR_INDEX 0x3 +#define UX_HOST_CLASS_HID_LOCAL_TAG_DESIGNATOR_MINIMUM 0x4 +#define UX_HOST_CLASS_HID_LOCAL_TAG_DESIGNATOR_MAXIMUM 0x5 +#define UX_HOST_CLASS_HID_LOCAL_TAG_STRING_INDEX 0x7 +#define UX_HOST_CLASS_HID_LOCAL_TAG_STRING_MINIMUM 0x8 +#define UX_HOST_CLASS_HID_LOCAL_TAG_STRING_MAXIMUM 0x9 +#define UX_HOST_CLASS_HID_LOCAL_TAG_DELIMITER 0xa + + +/* Define HID Class collection item types. */ + +#define UX_HOST_CLASS_HID_COLLECTION_PHYSICAL 0 +#define UX_HOST_CLASS_HID_COLLECTION_APPLICATION 1 +#define UX_HOST_CLASS_HID_COLLECTION_LOGICAL 2 + + +/* Define HID Class delimiter set. */ + +#define UX_HOST_CLASS_HID_DELIMITER_OPEN 1 +#define UX_HOST_CLASS_HID_DELIMITER_CLOSE 0 + + +/* Define HID Class item bit masks. */ + +#define UX_HOST_CLASS_HID_ITEM_CONSTANT 0x0001 +#define UX_HOST_CLASS_HID_ITEM_VARIABLE 0x0002 +#define UX_HOST_CLASS_HID_ITEM_RELATIVE 0x0004 +#define UX_HOST_CLASS_HID_ITEM_WRAP 0x0008 +#define UX_HOST_CLASS_HID_ITEM_NON_LINEAR 0x0010 +#define UX_HOST_CLASS_HID_ITEM_NO_PREFERRED_STATE 0x0020 +#define UX_HOST_CLASS_HID_ITEM_NULL_STATE 0x0040 +#define UX_HOST_CLASS_HID_ITEM_VOLATILE 0x0080 +#define UX_HOST_CLASS_HID_ITEM_BUFFERED_BYTES 0x0100 + + +/* Define HID Class commands. */ + +#define UX_HOST_CLASS_HID_GET_REPORT 0x01 +#define UX_HOST_CLASS_HID_GET_IDLE 0x02 +#define UX_HOST_CLASS_HID_GET_PROTOCOL 0x03 +#define UX_HOST_CLASS_HID_SET_REPORT 0x09 +#define UX_HOST_CLASS_HID_SET_IDLE 0x0A +#define UX_HOST_CLASS_HID_SET_PROTOCOL 0x0B + + +/* Define HID Class descriptors. */ + +#define UX_HOST_CLASS_HID_DESCRIPTOR 0x21 +#define UX_HOST_CLASS_HID_REPORT_DESCRIPTOR 0x22 +#define UX_HOST_CLASS_HID_PHYSICAL_DESCRIPTOR 0x23 + + +#define UX_HID_DESCRIPTOR_ENTRIES 7 +#define UX_HID_DESCRIPTOR_LENGTH 9 + + +/* Define HID Class page constants. */ + +#define UX_HOST_CLASS_HID_PAGE_GENERIC_DESKTOP_CONTROLS 0x01 +#define UX_HOST_CLASS_HID_PAGE_SIMULATION_CONTROLS 0x02 +#define UX_HOST_CLASS_HID_PAGE_VR_CONTROLS 0x03 +#define UX_HOST_CLASS_HID_PAGE_SPORT_CONTROLS 0x04 +#define UX_HOST_CLASS_HID_PAGE_GAME_CONTROLS 0x05 +#define UX_HOST_CLASS_HID_PAGE_GENERIC_DEVICE_CONTROLS 0x06 +#define UX_HOST_CLASS_HID_PAGE_KEYBOARD_KEYPAD 0x07 +#define UX_HOST_CLASS_HID_PAGE_LEDS 0x08 +#define UX_HOST_CLASS_HID_PAGE_BUTTON 0x09 +#define UX_HOST_CLASS_HID_PAGE_ORDINAL 0x0A +#define UX_HOST_CLASS_HID_PAGE_TELEPHONY 0x0B +#define UX_HOST_CLASS_HID_PAGE_CONSUMER 0x0C +#define UX_HOST_CLASS_HID_PAGE_DIGITIZER 0x0D +#define UX_HOST_CLASS_HID_PAGE_PHYSICAL_INTERFACE_DEVICE 0x0F +#define UX_HOST_CLASS_HID_PAGE_UNICODE 0x10 +#define UX_HOST_CLASS_HID_PAGE_ALPHANUMERIC_DISPLAY 0x14 +#define UX_HOST_CLASS_HID_PAGE_MEDICAL_INSTRUMENTS 0x40 +#define UX_HOST_CLASS_HID_PAGE_BAR_CODE_SCANNER 0x8C +#define UX_HOST_CLASS_HID_PAGE_SCALE_PAGE 0x8D +#define UX_HOST_CLASS_HID_PAGE_MAGNETIC_STRIPE_READING 0x8E +#define UX_HOST_CLASS_HID_PAGE_CAMERA_CONTROL_PAGE 0x90 + + +/* Define HID Class generic desktop page constants. */ + +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_UNDEFINED 0x00 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_POINTER 0x01 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_MOUSE 0x02 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_RESERVED 0x03 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_JOYSTICK 0x04 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_GAME PAD 0x05 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_KEYBOARD 0x06 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_KEYPAD 0x07 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_MULTI_AXIS_CONTROLLER 0x08 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_X 0x30 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_Y 0x31 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_Z 0x32 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_RX 0x33 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_RY 0x34 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_RZ 0x35 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SLIDER 0x36 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_DIAL 0x37 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_WHEEL 0x38 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_HAT_SWITCH 0x39 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_COUNTED_BUFFER 0x3A +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_BYTE_COUNT 0x3B +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_MOTION_WAKEUP 0x3C +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_START 0x3D +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SELECT 0x3E +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_VX 0x40 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_VY 0x41 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_VZ 0x42 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_VBRX 0x43 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_VBRY 0x44 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_VBRZ 0x45 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_VNO 0x46 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_FEATURE_NOTIFICATION 0x47 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_CONTROL 0x80 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_POWER_DOWN 0x81 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_SLEEP 0x82 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_WAKE_UP 0x83 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_CONTEXT_MENU 0x84 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_MAIN_MENU 0x85 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_APP_MENU 0x86 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_MENU_HELP 0x87 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_MENU_EXIT 0x88 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_MENU_SELECT 0x89 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_MENU_RIGHT 0x8A +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_MENU_LEFT 0x8B +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_MENU_UP 0x8C +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_MENU_DOWN 0x8D +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_COLD_RESTART 0x8E +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_WARM_RESTART 0x8F +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_D_PAD_UP 0x90 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_D_PAD_DOWN 0x91 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_D_PAD_RIGHT 0x92 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_D_PAD_LEFT 0x93 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_DOCK 0xA0 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_UNDOCK 0xA1 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_SETUP 0xA2 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_BREAK 0xA3 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_DEBUGGER_BREAK 0xA4 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_APPLICAION_BREAK 0xA5 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_APPLICATION_DEBUGGER_BREAK 0xA6 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_SPEAKER_MUTE 0xA7 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_HIBERNATE 0xA8 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_DISPLAY_INVERT 0xB0 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_DISPLAY_INTERNAL 0xB1 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_DISPLAY_EXTERNAL 0xB2 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_DISPLAY_BOTH 0xB3 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_DISPLAY_DUAL 0xB4 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_DISPLAY_TOGGLE 0xB5 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_DISPLAY_SWAP 0xB6 +#define UX_HOST_CLASS_HID_GENERIC_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE 0xB7 + + +/* Define HID Class game control page constants. */ + +#define UX_HOST_CLASS_HID_GAME_CONTROL_UNDEFINED 0x00 +#define UX_HOST_CLASS_HID_GAME_CONTROL_3D_GAME_CONTROLLER 0x01 +#define UX_HOST_CLASS_HID_GAME_CONTROL_PINBALL_DEVICE 0x02 +#define UX_HOST_CLASS_HID_GAME_CONTROL_GUN_DEVICE 0x03 +#define UX_HOST_CLASS_HID_GAME_CONTROL_POINT_OF_VIEW 0x20 +#define UX_HOST_CLASS_HID_GAME_CONTROL_TURN_RIGHT_LEFT 0x21 +#define UX_HOST_CLASS_HID_GAME_CONTROL_PITCH_FORWARD_BACKWARD 0x22 +#define UX_HOST_CLASS_HID_GAME_CONTROL_ROLL_RIGHT_LEFT 0x23 +#define UX_HOST_CLASS_HID_GAME_CONTROL_MOVE_RIGHT_LEFT 0x24 +#define UX_HOST_CLASS_HID_GAME_CONTROL_MOVE_FORWARD_BACKWARD 0x25 +#define UX_HOST_CLASS_HID_GAME_CONTROL_MOVE_UP_DOWN 0x26 +#define UX_HOST_CLASS_HID_GAME_CONTROL_LEAN_RIGHT_LEFT 0x27 +#define UX_HOST_CLASS_HID_GAME_CONTROL_LEAN_FORWARD_BACKWARD 0x28 +#define UX_HOST_CLASS_HID_GAME_CONTROL_HEIGHT_OF_POV 0x29 +#define UX_HOST_CLASS_HID_GAME_CONTROL_FLIPPER 0x2A +#define UX_HOST_CLASS_HID_GAME_CONTROL_SECONDARY_FLIPPER 0x2B +#define UX_HOST_CLASS_HID_GAME_CONTROL_BUMP 0x2C +#define UX_HOST_CLASS_HID_GAME_CONTROL_NEW_GAME 0x2D +#define UX_HOST_CLASS_HID_GAME_CONTROL_SHOOT_BALL 0x2E +#define UX_HOST_CLASS_HID_GAME_CONTROL_PLAYER 0x2F +#define UX_HOST_CLASS_HID_GAME_CONTROL_GUN_BOLT 0x30 +#define UX_HOST_CLASS_HID_GAME_CONTROL_GUN_CLIP 0x31 +#define UX_HOST_CLASS_HID_GAME_CONTROL_GUN_SELECTOR 0x32 +#define UX_HOST_CLASS_HID_GAME_CONTROL_GUN_SINGLE_SHOT 0x33 +#define UX_HOST_CLASS_HID_GAME_CONTROL_GUN_BURST 0x34 +#define UX_HOST_CLASS_HID_GAME_CONTROL_GUN_AUTOMATIC 0x35 +#define UX_HOST_CLASS_HID_GAME_CONTROL_GUN_SAFETY 0x36 +#define UX_HOST_CLASS_HID_GAME_CONTROL_GAMEAD_FIRE_JUMP 0x37 +#define UX_HOST_CLASS_HID_GAME_CONTROL_GAMEPAD_TRIGGER 0x39 + + +/* Define HID Class LED page constants. */ + +#define UX_HOST_CLASS_HID_LED_UNDEFINED 0x00 +#define UX_HOST_CLASS_HID_LED_NUM_LOCK 0x01 +#define UX_HOST_CLASS_HID_LED_CAPS_LOCK 0x02 +#define UX_HOST_CLASS_HID_LED_SCROLL_LOCK 0x03 +#define UX_HOST_CLASS_HID_LED_COMPOSE 0x04 +#define UX_HOST_CLASS_HID_LED_KANA 0x05 +#define UX_HOST_CLASS_HID_LED_POWER 0x06 +#define UX_HOST_CLASS_HID_LED_SHIFT 0x07 +#define UX_HOST_CLASS_HID_LED_DO_NOT_DISTURB 0x08 +#define UX_HOST_CLASS_HID_LED_MUTE 0x09 +#define UX_HOST_CLASS_HID_LED_TONE_ENABLE 0x0A +#define UX_HOST_CLASS_HID_LED_HIGH_CUT_FILTER 0x0B +#define UX_HOST_CLASS_HID_LED_LOW_CUT_FILTER 0x0C +#define UX_HOST_CLASS_HID_LED_EQUALIZER_ENABLE 0x0D +#define UX_HOST_CLASS_HID_LED_SOUND_FIELD_ON 0x0E +#define UX_HOST_CLASS_HID_LED_SURROUND_ON 0x0F +#define UX_HOST_CLASS_HID_LED_REPEAT 0x10 +#define UX_HOST_CLASS_HID_LED_STEREO 0x11 +#define UX_HOST_CLASS_HID_LED_SAMPLING_RATE_DETECT 0x12 +#define UX_HOST_CLASS_HID_LED_SPINNING 0x13 +#define UX_HOST_CLASS_HID_LED_CAV 0x14 +#define UX_HOST_CLASS_HID_LED_CLV 0x15 +#define UX_HOST_CLASS_HID_LED_RECORDING_FORMAT_DETECT 0x16 +#define UX_HOST_CLASS_HID_LED_OFF_HOOK 0x17 +#define UX_HOST_CLASS_HID_LED_RING 0x18 +#define UX_HOST_CLASS_HID_LED_MESSAGE_WAITING 0x19 +#define UX_HOST_CLASS_HID_LED_DATA_MODE 0x1A +#define UX_HOST_CLASS_HID_LED_BATTERY_OPERATION 0x1B +#define UX_HOST_CLASS_HID_LED_BATTERY_OK 0x1C +#define UX_HOST_CLASS_HID_LED_BATTERY_LOW 0x1D +#define UX_HOST_CLASS_HID_LED_SPEAKER 0x1E +#define UX_HOST_CLASS_HID_LED_HEAD_SET 0x1F +#define UX_HOST_CLASS_HID_LED_HOLD 0x20 +#define UX_HOST_CLASS_HID_LED_MICROPHONE 0x21 +#define UX_HOST_CLASS_HID_LED_COVERAGE 0x22 +#define UX_HOST_CLASS_HID_LED_NIGHT_MODE 0x23 +#define UX_HOST_CLASS_HID_LED_SEND_CALLS 0x24 +#define UX_HOST_CLASS_HID_LED_CALL_PICKUP 0x25 +#define UX_HOST_CLASS_HID_LED_CONFERENCE 0x26 +#define UX_HOST_CLASS_HID_LED_STAND_BY 0x27 +#define UX_HOST_CLASS_HID_LED_CAMERA_ON 0x28 +#define UX_HOST_CLASS_HID_LED_CAMERA_OFF 0x29 +#define UX_HOST_CLASS_HID_LED_ON_LINE 0x2A +#define UX_HOST_CLASS_HID_LED_OFF_LINE 0x2B +#define UX_HOST_CLASS_HID_LED_BUSY 0x2C +#define UX_HOST_CLASS_HID_LED_READY 0x2D +#define UX_HOST_CLASS_HID_LED_PAPER_OUT 0x2E +#define UX_HOST_CLASS_HID_LED_PAPER_JAM 0x2F +#define UX_HOST_CLASS_HID_LED_REMOTE 0x30 +#define UX_HOST_CLASS_HID_LED_FORWARD 0x31 +#define UX_HOST_CLASS_HID_LED_REVERSE 0x32 +#define UX_HOST_CLASS_HID_LED_STOP 0x33 +#define UX_HOST_CLASS_HID_LED_REWIND 0x34 +#define UX_HOST_CLASS_HID_LED_FAST_FORWARD 0x35 +#define UX_HOST_CLASS_HID_LED_PLAY 0x36 +#define UX_HOST_CLASS_HID_LED_PAUSE 0x37 +#define UX_HOST_CLASS_HID_LED_RECORD 0x38 +#define UX_HOST_CLASS_HID_LED_ERROR 0x39 +#define UX_HOST_CLASS_HID_LED_USAGE_SELECTED_INDICATOR 0x3A +#define UX_HOST_CLASS_HID_LED_USAGE_IN_USE_INDICATOR 0x3B +#define UX_HOST_CLASS_HID_LED_USAGE MULTI_MODE_INDICATOR 0x3C +#define UX_HOST_CLASS_HID_LED_INDICATOR_ON 0x3D +#define UX_HOST_CLASS_HID_LED_INDICATOR_FLASH 0x3E +#define UX_HOST_CLASS_HID_LED_INDICATOR_SLOW_BLINK 0x3F +#define UX_HOST_CLASS_HID_LED_INDICATOR_FAST_BLINK 0x40 +#define UX_HOST_CLASS_HID_LED_INDICATOR_OFF 0x41 +#define UX_HOST_CLASS_HID_LED_FLASH_ON_TIME 0x42 +#define UX_HOST_CLASS_HID_LED_SLOW_BLINK_ON_TIME 0x43 +#define UX_HOST_CLASS_HID_LED_SLOW_BLINK_OFF_TIME 0x44 +#define UX_HOST_CLASS_HID_LED_FAST_BLINK_ON_TIME 0x45 +#define UX_HOST_CLASS_HID_LED_FAST_BLINK_OFF_TIME 0x46 +#define UX_HOST_CLASS_HID_LED_USAGE_INDICATOR_COLOR 0x47 +#define UX_HOST_CLASS_HID_LED_INDICATOR_RED 0x48 +#define UX_HOST_CLASS_HID_LED_INDICATOR_GREEN 0x49 +#define UX_HOST_CLASS_HID_LED_INDICATOR_AMBER 0x4A +#define UX_HOST_CLASS_HID_LED_GENERIC_INDICATOR 0x4B +#define UX_HOST_CLASS_HID_LED_SYSTEM_SUSPEND 0x4C +#define UX_HOST_CLASS_HID_LED_EXTERNAL_POWER_CONNECTED 0x4D + + +/* Define HID Class consumer page constants. */ + +#define UX_HOST_CLASS_HID_CONSUMER_UNASSIGNED 0x00 +#define UX_HOST_CLASS_HID_CONSUMER_REMOTE_CONTROL 0x01 +#define UX_HOST_CLASS_HID_CONSUMER_NUMERIC_KEY_PAD 0x02 +#define UX_HOST_CLASS_HID_CONSUMER_PROGRAMMABLE_BUTTONS 0x03 +#define UX_HOST_CLASS_HID_CONSUMER_MICROPHONE 0x04 +#define UX_HOST_CLASS_HID_CONSUMER_HEADPHONE 0x05 +#define UX_HOST_CLASS_HID_CONSUMER_GRAPHIC_EQUALIZER 0x06 +#define UX_HOST_CLASS_HID_CONSUMER_PLUS_10 0x20 +#define UX_HOST_CLASS_HID_CONSUMER_PLUS_100 0x21 +#define UX_HOST_CLASS_HID_CONSUMER_AM_PM 0x22 +#define UX_HOST_CLASS_HID_CONSUMER_POWER 0x30 +#define UX_HOST_CLASS_HID_CONSUMER_RESET 0x31 +#define UX_HOST_CLASS_HID_CONSUMER_SLEEP 0x32 +#define UX_HOST_CLASS_HID_CONSUMER_SLEEP_AFTER 0x33 +#define UX_HOST_CLASS_HID_CONSUMER_SLEEP_MODE_RTC 0x34 +#define UX_HOST_CLASS_HID_CONSUMER_ILLUMINATION 0x35 +#define UX_HOST_CLASS_HID_CONSUMER_FUNCTION_BUTTONS 0x36 +#define UX_HOST_CLASS_HID_CONSUMER_MENU 0x40 +#define UX_HOST_CLASS_HID_CONSUMER_MENU_PICK 0x41 +#define UX_HOST_CLASS_HID_CONSUMER_MENU_UP 0x42 +#define UX_HOST_CLASS_HID_CONSUMER_MENU_DOWN 0x43 +#define UX_HOST_CLASS_HID_CONSUMER_MENU_LEFT 0x44 +#define UX_HOST_CLASS_HID_CONSUMER_MENU_RIGHT 0x45 +#define UX_HOST_CLASS_HID_CONSUMER_MENU_ESCAPE 0x46 +#define UX_HOST_CLASS_HID_CONSUMER_MENU_VALUE_INCREASE 0x47 +#define UX_HOST_CLASS_HID_CONSUMER_MENU_VALUE_DECREASE 0x48 +#define UX_HOST_CLASS_HID_CONSUMER_DATA_ON_SCREEN 0x60 +#define UX_HOST_CLASS_HID_CONSUMER_CLOSED_CAPTION 0x61 +#define UX_HOST_CLASS_HID_CONSUMER_CLOSED_CAPTION_SELECT 0x62 +#define UX_HOST_CLASS_HID_CONSUMER_VCR_TV 0x63 +#define UX_HOST_CLASS_HID_CONSUMER_BROADCAST_MODE 0x64 +#define UX_HOST_CLASS_HID_CONSUMER_SNAPSHOT 0x65 +#define UX_HOST_CLASS_HID_CONSUMER_STILL 0x66 +#define UX_HOST_CLASS_HID_CONSUMER_SELECTION 0x80 +#define UX_HOST_CLASS_HID_CONSUMER_ASSIGN_SELECTION 0x81 +#define UX_HOST_CLASS_HID_CONSUMER_MODE_STEP 0x82 +#define UX_HOST_CLASS_HID_CONSUMER_RECALL_LAST 0x83 +#define UX_HOST_CLASS_HID_CONSUMER_ENTER_CHANNEL 0x84 +#define UX_HOST_CLASS_HID_CONSUMER_ORDER_MOVIE 0x85 +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_L 0x86 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECTION 0x87 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_COMPUTER 0x88 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_TV 0x89 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_WWW 0x8A +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_DVD 0x8B +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_TELEPHONE 0x8C +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_PROGRAM_GUIDE 0x8D +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_VIDEO_PHONE 0x8E +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_GAMES 0x8F +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_MESSAGES 0x90 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_CD 0x91 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_VCR 0x92 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_TUNER 0x93 +#define UX_HOST_CLASS_HID_CONSUMER_QUIT 0x94 +#define UX_HOST_CLASS_HID_CONSUMER_HELP 0x95 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_TAPE 0x96 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_CABLE 0x97 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_SATELLITE 0x98 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_SECURITY 0x99 +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_HOME 0x9A +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT_CALL 0x9B +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_INCREMENT 0x9C +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_DECREMENT 0x9D +#define UX_HOST_CLASS_HID_CONSUMER_MEDIA_SELECT 0x9E +#define UX_HOST_CLASS_HID_CONSUMER_VCR_PLUS 0xA0 +#define UX_HOST_CLASS_HID_CONSUMER_ONCE 0xA1 +#define UX_HOST_CLASS_HID_CONSUMER_DAILY 0xA2 +#define UX_HOST_CLASS_HID_CONSUMER_WEEKLY 0xA3 +#define UX_HOST_CLASS_HID_CONSUMER_MONTHLY 0xA4 +#define UX_HOST_CLASS_HID_CONSUMER_PLAY 0xB0 +#define UX_HOST_CLASS_HID_CONSUMER_PAUSE 0xB1 +#define UX_HOST_CLASS_HID_CONSUMER_RECORD 0xB2 +#define UX_HOST_CLASS_HID_CONSUMER_FAST_FORWARD 0xB3 +#define UX_HOST_CLASS_HID_CONSUMER_REWIND 0xB4 +#define UX_HOST_CLASS_HID_CONSUMER_SCAN_NEXT_TRACK 0xB5 +#define UX_HOST_CLASS_HID_CONSUMER_SCAN_PREVIOUS_TRACK 0xB6 +#define UX_HOST_CLASS_HID_CONSUMER_STOP 0xB7 +#define UX_HOST_CLASS_HID_CONSUMER_EJECT 0xB8 +#define UX_HOST_CLASS_HID_CONSUMER_RANDOM_PLAY 0xB9 +#define UX_HOST_CLASS_HID_CONSUMER_SELECT_DISC 0xBA +#define UX_HOST_CLASS_HID_CONSUMER_ENTER_DISC 0xBB +#define UX_HOST_CLASS_HID_CONSUMER_REPEAT 0xBC +#define UX_HOST_CLASS_HID_CONSUMER_TRACKING 0xBD +#define UX_HOST_CLASS_HID_CONSUMER_TRACK_NORMAL 0xBE +#define UX_HOST_CLASS_HID_CONSUMER_SLOW_TRACKING 0xBF +#define UX_HOST_CLASS_HID_CONSUMER_FRAME_FORWARD 0xC0 +#define UX_HOST_CLASS_HID_CONSUMER_FRAME_BACK 0xC1 +#define UX_HOST_CLASS_HID_CONSUMER_MARK 0xC2 +#define UX_HOST_CLASS_HID_CONSUMER_CLEAR_MARK 0xC3 +#define UX_HOST_CLASS_HID_CONSUMER_REPEAT_FROM_MARK 0xC4 +#define UX_HOST_CLASS_HID_CONSUMER_RETURN_TO_MARK 0xC5 +#define UX_HOST_CLASS_HID_CONSUMER_SEARCH_MARK_FORWARD 0xC6 +#define UX_HOST_CLASS_HID_CONSUMER_SEARCH_MARK_BACKWARDS 0xC7 +#define UX_HOST_CLASS_HID_CONSUMER_COUNTER_RESET 0xC8 +#define UX_HOST_CLASS_HID_CONSUMER_SHOW_COUNTER 0xC9 +#define UX_HOST_CLASS_HID_CONSUMER_TRACKING_INCREMENT 0xCA +#define UX_HOST_CLASS_HID_CONSUMER_TRACKING_DECREMENT 0xCB +#define UX_HOST_CLASS_HID_CONSUMER_STOP_EJECT 0xCC +#define UX_HOST_CLASS_HID_CONSUMER_PLAY_PAUSE 0xCD +#define UX_HOST_CLASS_HID_CONSUMER_PLAY_SKIP 0xCE +#define UX_HOST_CLASS_HID_CONSUMER_VOLUME 0xE0 +#define UX_HOST_CLASS_HID_CONSUMER_BALANCE 0xE1 +#define UX_HOST_CLASS_HID_CONSUMER_MUTE 0xE2 +#define UX_HOST_CLASS_HID_CONSUMER_BASS 0xE3 +#define UX_HOST_CLASS_HID_CONSUMER_TREBLE 0xE4 +#define UX_HOST_CLASS_HID_CONSUMER_BASS_BOOST 0xE5 +#define UX_HOST_CLASS_HID_CONSUMER_SURROUND_MODE 0xE6 +#define UX_HOST_CLASS_HID_CONSUMER_LOUDNESS 0xE7 +#define UX_HOST_CLASS_HID_CONSUMER_MPX 0xE8 +#define UX_HOST_CLASS_HID_CONSUMER_VOLUME_INCREMENT 0xE9 +#define UX_HOST_CLASS_HID_CONSUMER_VOLUME_DECREMENT 0xEA +#define UX_HOST_CLASS_HID_CONSUMER_SPEED_SELECT 0xF0 +#define UX_HOST_CLASS_HID_CONSUMER_PLAYBACK_SPEED 0xF1 +#define UX_HOST_CLASS_HID_CONSUMER_STANDARD_PLAY 0xF2 +#define UX_HOST_CLASS_HID_CONSUMER_LONG_PLAY 0xF3 +#define UX_HOST_CLASS_HID_CONSUMER_EXTENDED_PLAY 0xF4 +#define UX_HOST_CLASS_HID_CONSUMER_SLOW 0xF5 +#define UX_HOST_CLASS_HID_CONSUMER_FAN_ENABLE 0xF6 +#define UX_HOST_CLASS_HID_CONSUMER_FAN_SPEED 0x100 +#define UX_HOST_CLASS_HID_CONSUMER_LIGHT_ENABLE 0x101 +#define UX_HOST_CLASS_HID_CONSUMER_LIGHT_ILLUMINATION_LEVEL 0x102 +#define UX_HOST_CLASS_HID_CONSUMER_CLIMATE_CONTROL_ENABLE 0x103 +#define UX_HOST_CLASS_HID_CONSUMER_ROOM_TEMPERATURE 0x104 +#define UX_HOST_CLASS_HID_CONSUMER_SECURITY_ENABLE 0x105 +#define UX_HOST_CLASS_HID_CONSUMER_FIRE_ALARM 0x106 +#define UX_HOST_CLASS_HID_CONSUMER_POLICE_ALARM 0x107 +#define UX_HOST_CLASS_HID_CONSUMER_PROXIMITY 0x108 +#define UX_HOST_CLASS_HID_CONSUMER_MOTION 0x109 +#define UX_HOST_CLASS_HID_CONSUMER_DURESS_ALARM 0x10A +#define UX_HOST_CLASS_HID_CONSUMER_HOLDUP_ALARM 0x10B +#define UX_HOST_CLASS_HID_CONSUMER_MEDICAL_ALARM 0x10C +#define UX_HOST_CLASS_HID_CONSUMER_BALANCE_RIGHT 0x10D +#define UX_HOST_CLASS_HID_CONSUMER_BALANCE_LEFT 0x150 +#define UX_HOST_CLASS_HID_CONSUMER_BASS_INCREMENT 0x151 +#define UX_HOST_CLASS_HID_CONSUMER_BASS_DECREMENT 0x152 +#define UX_HOST_CLASS_HID_CONSUMER_TREBLE_INCREMENT 0x153 +#define UX_HOST_CLASS_HID_CONSUMER_TREBLE_DECREMENT 0x154 +#define UX_HOST_CLASS_HID_CONSUMER_SPEAKER_SYSTEM 0x155 +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_LEFT 0x160 +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_RIGHT 0x161 +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_CENTER 0x162 +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_FRONT 0x163 +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_CENTER_FRONT 0x164 +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_SIDE 0x165 +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_SURROUND 0x166 +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_LOW_FREQUENCY 0x167 +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_TOP 0x168 +#define UX_HOST_CLASS_HID_CONSUMER_CHANNEL_UNKNOWN 0x169 +#define UX_HOST_CLASS_HID_CONSUMER_SUB_CHANNEL 0x16A +#define UX_HOST_CLASS_HID_CONSUMER_SUB_CHANNEL_INCREMENT 0x170 +#define UX_HOST_CLASS_HID_CONSUMER_SUB_CHANNEL_DECREMENT 0x171 +#define UX_HOST_CLASS_HID_CONSUMER_ALTERNATE_AUDIO_INCREMENT 0x172 +#define UX_HOST_CLASS_HID_CONSUMER_ALTERNATE_AUDIO_DECREMENT 0x173 +#define UX_HOST_CLASS_HID_CONSUMER_APPLICATION_LAUNCH_BUTTONS 0x174 +#define UX_HOST_CLASS_HID_CONSUMER_AL_LAUNCH_BUTTON_CONFIGURATION 0x180 +#define UX_HOST_CLASS_HID_CONSUMER_AL_PROGRAMMABLE_BUTTON 0x181 +#define UX_HOST_CLASS_HID_CONSUMER_AL_CONSUMER_CONTROL_CONFIGURATION 0x182 +#define UX_HOST_CLASS_HID_CONSUMER_AL_WORD_PROCESSOR 0x183 +#define UX_HOST_CLASS_HID_CONSUMER_AL_TEXT_EDITOR 0x184 +#define UX_HOST_CLASS_HID_CONSUMER_AL_SPREADSHEET 0x185 +#define UX_HOST_CLASS_HID_CONSUMER_AL_GRAPHICS_EDITOR 0x186 +#define UX_HOST_CLASS_HID_CONSUMER_AL_PRESENTATION_APP 0x187 +#define UX_HOST_CLASS_HID_CONSUMER_AL_DATABASE_APP 0x188 +#define UX_HOST_CLASS_HID_CONSUMER_AL_EMAIL_READER 0x189 +#define UX_HOST_CLASS_HID_CONSUMER_AL_NEWSREADER 0x18A +#define UX_HOST_CLASS_HID_CONSUMER_AL_VOICEMAIL 0x18B +#define UX_HOST_CLASS_HID_CONSUMER_AL_CONTACTS_ADDRESS_BOOK 0x18C +#define UX_HOST_CLASS_HID_CONSUMER_AL_CALENDAR_SCHEDULE 0x18D +#define UX_HOST_CLASS_HID_CONSUMER_AL_TASK_PROJECT_MANAGER 0x18E +#define UX_HOST_CLASS_HID_CONSUMER_AL_LOG_JOURNAL_TIMECARD 0x18F +#define UX_HOST_CLASS_HID_CONSUMER_AL_CHECKBOOK_FINANCE 0x190 +#define UX_HOST_CLASS_HID_CONSUMER_AL_CALCULATOR 0x191 +#define UX_HOST_CLASS_HID_CONSUMER_AL_A_V_CAPTURE_PLAYBACK 0x192 +#define UX_HOST_CLASS_HID_CONSUMER_AL_LOCAL_MACHINE_BROWSER 0x193 +#define UX_HOST_CLASS_HID_CONSUMER_AL_LAN_WAN_BROWSER 0x194 +#define UX_HOST_CLASS_HID_CONSUMER_AL_INTERNET_BROWSER 0x195 +#define UX_HOST_CLASS_HID_CONSUMER_AL_REMOTE_NETWORKING 0x196 +#define UX_HOST_CLASS_HID_CONSUMER_AL_NETWORK_CONFERENCE 0x197 +#define UX_HOST_CLASS_HID_CONSUMER_AL_NETWORK_CHAT 0x198 +#define UX_HOST_CLASS_HID_CONSUMER_AL_TELEPHONY_DIALER 0x199 +#define UX_HOST_CLASS_HID_CONSUMER_AL_LOGON 0x19A +#define UX_HOST_CLASS_HID_CONSUMER_AL_LOGOFF 0x19B +#define UX_HOST_CLASS_HID_CONSUMER_AL_LOGON_LOGOFF 0x19C +#define UX_HOST_CLASS_HID_CONSUMER_AL_SCREENSAVER 0x19D +#define UX_HOST_CLASS_HID_CONSUMER_AL_CONTROL_PANEL 0x19E +#define UX_HOST_CLASS_HID_CONSUMER_AL_COMMAND_LINE_PROCESSOR 0x19F +#define UX_HOST_CLASS_HID_CONSUMER_AL_PROCESS_MANAGER 0x1A0 +#define UX_HOST_CLASS_HID_CONSUMER_AL_SELECT_APPLICATION 0x1A1 +#define UX_HOST_CLASS_HID_CONSUMER_AL_NEXT_APPLICATION 0x1A2 +#define UX_HOST_CLASS_HID_CONSUMER_AL_PREVIOUS_APPLICATION 0x1A3 +#define UX_HOST_CLASS_HID_CONSUMER_AL_PREEMPTIVE_HALT_APPLICATION 0x1A4 +#define UX_HOST_CLASS_HID_CONSUMER_AL_INTEGRATED_HELP_CENTER 0x1A5 +#define UX_HOST_CLASS_HID_CONSUMER_AL_DOCUMENTS 0x1A6 +#define UX_HOST_CLASS_HID_CONSUMER_AL_THESAURUS 0x1A7 +#define UX_HOST_CLASS_HID_CONSUMER_AL_DICTIONARY 0x1A8 +#define UX_HOST_CLASS_HID_CONSUMER_AL_DESKTOP 0x1A9 +#define UX_HOST_CLASS_HID_CONSUMER_AL_SPELL_CHECK 0x1AA +#define UX_HOST_CLASS_HID_CONSUMER_AL_GRAMMAR_CHECK 0x1AB +#define UX_HOST_CLASS_HID_CONSUMER_AL_WIRELESS_STATUS 0x1AC +#define UX_HOST_CLASS_HID_CONSUMER_AL_KEYBOARD_LAYOUT 0x1AD +#define UX_HOST_CLASS_HID_CONSUMER_AL_VIRUS_PROTECTION 0x1AE +#define UX_HOST_CLASS_HID_CONSUMER_AL_ENCRYPTION 0x1AF +#define UX_HOST_CLASS_HID_CONSUMER_AL_SCREEN_SAVER 0x1B0 +#define UX_HOST_CLASS_HID_CONSUMER_AL_ALARMS 0x1B1 +#define UX_HOST_CLASS_HID_CONSUMER_AL_CLOCK 0x1B2 +#define UX_HOST_CLASS_HID_CONSUMER_AL_FILE_BROWSER 0x1B3 +#define UX_HOST_CLASS_HID_CONSUMER_AL_POWER_STATUS 0x1B4 +#define UX_HOST_CLASS_HID_CONSUMER_AC_NEW 0x1B5 +#define UX_HOST_CLASS_HID_CONSUMER_AC_OPEN 0x201 +#define UX_HOST_CLASS_HID_CONSUMER_AC_CLOSE 0x202 +#define UX_HOST_CLASS_HID_CONSUMER_AC_EXIT 0x203 +#define UX_HOST_CLASS_HID_CONSUMER_AC_MAXIMIZE 0x204 +#define UX_HOST_CLASS_HID_CONSUMER_AC_MINIMIZE 0x205 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SAVE 0x206 +#define UX_HOST_CLASS_HID_CONSUMER_AC_PRINT 0x207 +#define UX_HOST_CLASS_HID_CONSUMER_AC_PROPERTIES 0x208 +#define UX_HOST_CLASS_HID_CONSUMER_AC_UNDO 0x209 +#define UX_HOST_CLASS_HID_CONSUMER_AC_COPY 0x21A +#define UX_HOST_CLASS_HID_CONSUMER_AC_CUT 0x21B +#define UX_HOST_CLASS_HID_CONSUMER_AC_PASTE 0x21C +#define UX_HOST_CLASS_HID_CONSUMER_AC_SELECT_ALL 0x21D +#define UX_HOST_CLASS_HID_CONSUMER_AC_FIND 0x21E +#define UX_HOST_CLASS_HID_CONSUMER_AC_FIND_AND_REPLACE 0x21F +#define UX_HOST_CLASS_HID_CONSUMER_AC_SEARCH 0x220 +#define UX_HOST_CLASS_HID_CONSUMER_AC_GO_TO 0x221 +#define UX_HOST_CLASS_HID_CONSUMER_AC_HOME 0x222 +#define UX_HOST_CLASS_HID_CONSUMER_AC_BACK 0x223 +#define UX_HOST_CLASS_HID_CONSUMER_AC_FORWARD 0x224 +#define UX_HOST_CLASS_HID_CONSUMER_AC_STOP 0x225 +#define UX_HOST_CLASS_HID_CONSUMER_AC_REFRESH 0x226 +#define UX_HOST_CLASS_HID_CONSUMER_AC_PREVIOUS_LINK 0x227 +#define UX_HOST_CLASS_HID_CONSUMER_AC_NEXT_LINK 0x228 +#define UX_HOST_CLASS_HID_CONSUMER_AC_BOOKMARKS 0x229 +#define UX_HOST_CLASS_HID_CONSUMER_AC_HISTORY 0x22A +#define UX_HOST_CLASS_HID_CONSUMER_AC_SUBSCRIPTIONS 0x22B +#define UX_HOST_CLASS_HID_CONSUMER_AC_ZOOM_IN 0x22C +#define UX_HOST_CLASS_HID_CONSUMER_AC_ZOOM_OUT 0x22D +#define UX_HOST_CLASS_HID_CONSUMER_AC_ZOOM 0x22E +#define UX_HOST_CLASS_HID_CONSUMER_AC_FULL_SCREEN_VIEW 0x22F +#define UX_HOST_CLASS_HID_CONSUMER_AC_NORMAL_VIEW 0x230 +#define UX_HOST_CLASS_HID_CONSUMER_AC_VIEW_TOGGLE 0x231 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SCROLL_UP 0x232 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SCROLL_DOWN 0x233 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SCROLL 0x234 +#define UX_HOST_CLASS_HID_CONSUMER_AC_PAN_LEFT 0x235 +#define UX_HOST_CLASS_HID_CONSUMER_AC_PAN_RIGHT 0x236 +#define UX_HOST_CLASS_HID_CONSUMER_AC_PAN 0x237 +#define UX_HOST_CLASS_HID_CONSUMER_AC_NEW_WINDOW 0x238 +#define UX_HOST_CLASS_HID_CONSUMER_AC_TILE_HORIZONTALLY 0x239 +#define UX_HOST_CLASS_HID_CONSUMER_AC_TILE_VERTICALLY 0x23A +#define UX_HOST_CLASS_HID_CONSUMER_AC_FORMAT 0x23B +#define UX_HOST_CLASS_HID_CONSUMER_AC_EDIT 0x23C +#define UX_HOST_CLASS_HID_CONSUMER_AC_BOLD 0x23D +#define UX_HOST_CLASS_HID_CONSUMER_AC_ITALICS 0x23E +#define UX_HOST_CLASS_HID_CONSUMER_AC_UNDERLINE 0x23F +#define UX_HOST_CLASS_HID_CONSUMER_AC_STRIKETHROUGH 0x240 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SUBSCRIPT 0x241 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SUPERSCRIPT 0x242 +#define UX_HOST_CLASS_HID_CONSUMER_AC_ALL_CAPS 0x243 +#define UX_HOST_CLASS_HID_CONSUMER_AC_ROTATE 0x244 +#define UX_HOST_CLASS_HID_CONSUMER_AC_RESIZE 0x245 +#define UX_HOST_CLASS_HID_CONSUMER_AC_FLIP_HORIZONTAL 0x246 +#define UX_HOST_CLASS_HID_CONSUMER_AC_FLIP_VERTICAL 0x247 +#define UX_HOST_CLASS_HID_CONSUMER_AC_MIRROR_HORIZONTAL 0x248 +#define UX_HOST_CLASS_HID_CONSUMER_AC_MIRROR_VERTICAL 0x249 +#define UX_HOST_CLASS_HID_CONSUMER_AC_FONT_SELECT 0x24A +#define UX_HOST_CLASS_HID_CONSUMER_AC_FONT_COLOR 0x24B +#define UX_HOST_CLASS_HID_CONSUMER_AC_FONT_SIZE 0x24C +#define UX_HOST_CLASS_HID_CONSUMER_AC_JUSTIFY_LEFT 0x24D +#define UX_HOST_CLASS_HID_CONSUMER_AC_JUSTIFY_CENTER_H 0x24E +#define UX_HOST_CLASS_HID_CONSUMER_AC_JUSTIFY_RIGHT 0x24F +#define UX_HOST_CLASS_HID_CONSUMER_AC_JUSTIFY_BLOCK_H 0x250 +#define UX_HOST_CLASS_HID_CONSUMER_AC_JUSTIFY_TOP 0x251 +#define UX_HOST_CLASS_HID_CONSUMER_AC_JUSTIFY_CENTER_V 0x252 +#define UX_HOST_CLASS_HID_CONSUMER_AC_JUSTIFY_BOTTOM 0x253 +#define UX_HOST_CLASS_HID_CONSUMER_AC_JUSTIFY_BLOCK_V 0x254 +#define UX_HOST_CLASS_HID_CONSUMER_AC_INDENT_DECREASE 0x255 +#define UX_HOST_CLASS_HID_CONSUMER_AC_INDENT_INCREASE 0x256 +#define UX_HOST_CLASS_HID_CONSUMER_AC_NUMBERED_LIST 0x257 +#define UX_HOST_CLASS_HID_CONSUMER_AC_RESTART_NUMBERING 0x258 +#define UX_HOST_CLASS_HID_CONSUMER_AC_BULLETED_LIST 0x259 +#define UX_HOST_CLASS_HID_CONSUMER_AC_PROMOTE 0x25A +#define UX_HOST_CLASS_HID_CONSUMER_AC_DEMOTE 0x25B +#define UX_HOST_CLASS_HID_CONSUMER_AC_YES 0x25C +#define UX_HOST_CLASS_HID_CONSUMER_AC_NO 0x25D +#define UX_HOST_CLASS_HID_CONSUMER_AC_CANCEL 0x25E +#define UX_HOST_CLASS_HID_CONSUMER_AC_CATALOG 0x25F +#define UX_HOST_CLASS_HID_CONSUMER_AC_BUY_CHECKOUT 0x260 +#define UX_HOST_CLASS_HID_CONSUMER_AC_ADD_TO_CART 0x261 +#define UX_HOST_CLASS_HID_CONSUMER_AC_EXPAND 0x262 +#define UX_HOST_CLASS_HID_CONSUMER_AC_EXPAND_ALL 0x263 +#define UX_HOST_CLASS_HID_CONSUMER_AC_COLLAPSE 0x264 +#define UX_HOST_CLASS_HID_CONSUMER_AC_COLLAPSE_ALL 0x265 +#define UX_HOST_CLASS_HID_CONSUMER_AC_PRINT_PREVIEW 0x266 +#define UX_HOST_CLASS_HID_CONSUMER_AC_PASTE_SPECIAL 0x267 +#define UX_HOST_CLASS_HID_CONSUMER_AC_INSERT_MODE 0x268 +#define UX_HOST_CLASS_HID_CONSUMER_AC_DELETE 0x269 +#define UX_HOST_CLASS_HID_CONSUMER_AC_LOCK 0x26A +#define UX_HOST_CLASS_HID_CONSUMER_AC_UNLOCK 0x26B +#define UX_HOST_CLASS_HID_CONSUMER_AC_PROTECT 0x26C +#define UX_HOST_CLASS_HID_CONSUMER_AC_UNPROTECT 0x26D +#define UX_HOST_CLASS_HID_CONSUMER_AC_ATTACH_COMMENT 0x26E +#define UX_HOST_CLASS_HID_CONSUMER_AC_DELETE_COMMENT 0x26F +#define UX_HOST_CLASS_HID_CONSUMER_AC_VIEW_COMMENT 0x270 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SELECT_WORD 0x271 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SELECT_SENTENCE 0x272 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SELECT_PARAGRAPH 0x273 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SELECT_COLUMN 0x274 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SELECT_ROW 0x275 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SELECT_TABLE 0x276 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SELECT_OBJECT 0x277 +#define UX_HOST_CLASS_HID_CONSUMER_AC_REDO_REPEAT 0x278 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SORT 0x279 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SORT_ASCENDING 0x27A +#define UX_HOST_CLASS_HID_CONSUMER_AC_SORT_DESCENDING 0x27B +#define UX_HOST_CLASS_HID_CONSUMER_AC_FILTER 0x27C +#define UX_HOST_CLASS_HID_CONSUMER_AC_SET_CLOCK 0x27D +#define UX_HOST_CLASS_HID_CONSUMER_AC_VIEW_CLOCK 0x27E +#define UX_HOST_CLASS_HID_CONSUMER_AC_SELECT_TIME_ZONE 0x27F +#define UX_HOST_CLASS_HID_CONSUMER_AC_EDIT_TIME_ZONES 0x280 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SET_ALARM 0x281 +#define UX_HOST_CLASS_HID_CONSUMER_AC_CLEAR_ALARM 0x282 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SNOOZE_ALARM 0x283 +#define UX_HOST_CLASS_HID_CONSUMER_AC_RESET_ALARM 0x284 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SYNCHRONIZE 0x285 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SEND_RECEIVE 0x286 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SEND_TO 0x287 +#define UX_HOST_CLASS_HID_CONSUMER_AC_REPLY 0x288 +#define UX_HOST_CLASS_HID_CONSUMER_AC_REPLY_ALL 0x289 +#define UX_HOST_CLASS_HID_CONSUMER_AC_FORWARD_MSG 0x28A +#define UX_HOST_CLASS_HID_CONSUMER_AC_SEND 0x28B +#define UX_HOST_CLASS_HID_CONSUMER_AC_ATTACH_FILE 0x28C +#define UX_HOST_CLASS_HID_CONSUMER_AC_UPLOAD 0x28D +#define UX_HOST_CLASS_HID_CONSUMER_AC_DOWNLOAD 0x28E +#define UX_HOST_CLASS_HID_CONSUMER_AC_SET_BORDERS 0x28F +#define UX_HOST_CLASS_HID_CONSUMER_AC_INSERT_ROW 0x290 +#define UX_HOST_CLASS_HID_CONSUMER_AC_INSERT_COLUMN 0x291 +#define UX_HOST_CLASS_HID_CONSUMER_AC_INSERT_FILE 0x292 +#define UX_HOST_CLASS_HID_CONSUMER_AC_INSERT_PICTURE 0x293 +#define UX_HOST_CLASS_HID_CONSUMER_AC_INSERT_OBJECT 0x294 +#define UX_HOST_CLASS_HID_CONSUMER_AC_INSERT_SYMBOL 0x295 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SAVE_CLOSE 0x296 +#define UX_HOST_CLASS_HID_CONSUMER_AC_RENAME 0x297 +#define UX_HOST_CLASS_HID_CONSUMER_AC_MERGE 0x298 +#define UX_HOST_CLASS_HID_CONSUMER_AC_SPLIT 0x299 +#define UX_HOST_CLASS_HID_CONSUMER_AC_DISRIBUTE_HORIZONTALLY 0x29A +#define UX_HOST_CLASS_HID_CONSUMER_AC_DISTRIBUTE_VERTICALLY 0x29B + +/* Define HID Report Types. */ + +#define UX_HOST_CLASS_HID_REPORT_TYPE_INPUT 0x1 +#define UX_HOST_CLASS_HID_REPORT_TYPE_OUTPUT 0x2 +#define UX_HOST_CLASS_HID_REPORT_TYPE_FEATURE 0x3 + +/* Define HID Class report callback structure. */ + +#ifndef UX_HOST_CLASS_HID_USAGES +#define UX_HOST_CLASS_HID_USAGES 1024 +#endif + +#define UX_HOST_CLASS_HID_MAX_GLOBAL 4 +#define UX_HOST_CLASS_HID_MAX_COLLECTION 4 + +/* Define HID Class descriptor. */ + +typedef struct UX_HID_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bcdHID; + ULONG bCountryCode; + ULONG bNumDescriptor; + ULONG bReportDescriptorType; + ULONG wItemLength; +} UX_HID_DESCRIPTOR; + + +typedef struct UX_HOST_CLASS_HID_REPORT_CALLBACK_STRUCT +{ + + struct UX_HOST_CLASS_HID_CLIENT_STRUCT + *ux_host_class_hid_report_callback_client; + ULONG ux_host_class_hid_report_callback_id; + ULONG ux_host_class_hid_report_callback_status; + ULONG ux_host_class_hid_report_callback_flags; + ULONG ux_host_class_hid_report_callback_value; + ULONG ux_host_class_hid_report_callback_usage; + ULONG ux_host_class_hid_report_callback_length; + ULONG ux_host_class_hid_report_callback_actual_length; + VOID *ux_host_class_hid_report_callback_buffer; + VOID (*ux_host_class_hid_report_callback_function) (struct UX_HOST_CLASS_HID_REPORT_CALLBACK_STRUCT *); +} UX_HOST_CLASS_HID_REPORT_CALLBACK; + + + +typedef struct UX_HOST_CLASS_HID_REPORT_GET_ID_STRUCT +{ + + ULONG ux_host_class_hid_report_get_id; + ULONG ux_host_class_hid_report_get_type; + struct UX_HOST_CLASS_HID_REPORT_STRUCT + *ux_host_class_hid_report_get_report; +} UX_HOST_CLASS_HID_REPORT_GET_ID; + + +/* Define HID Class local item structure. */ + +typedef struct UX_HOST_CLASS_HID_LOCAL_ITEM_STRUCT +{ + + ULONG ux_host_class_hid_local_item_usages[UX_HOST_CLASS_HID_USAGES]; + ULONG ux_host_class_hid_local_item_number_usage; + ULONG ux_host_class_hid_local_item_usage_min; + ULONG ux_host_class_hid_local_item_usage_max; + ULONG ux_host_class_hid_local_item_delimiter_level; + ULONG ux_host_class_hid_local_item_delimiter_branch; +} UX_HOST_CLASS_HID_LOCAL_ITEM; + + +/* Define HID Class global item structure. */ + +typedef struct UX_HOST_CLASS_HID_GLOBAL_ITEM_STRUCT +{ + + ULONG ux_host_class_hid_global_item_usage_page; + SLONG ux_host_class_hid_global_item_logical_min; + SLONG ux_host_class_hid_global_item_logical_max; + SLONG ux_host_class_hid_global_item_physical_min; + SLONG ux_host_class_hid_global_item_physical_max; + ULONG ux_host_class_hid_global_item_unit_expo; + ULONG ux_host_class_hid_global_item_unit; + ULONG ux_host_class_hid_global_item_report_size; + ULONG ux_host_class_hid_global_item_report_id; + ULONG ux_host_class_hid_global_item_report_count; +} UX_HOST_CLASS_HID_GLOBAL_ITEM; + + +/* Define HID Class field structure. */ + +typedef struct UX_HOST_CLASS_HID_FIELD_STRUCT +{ + + ULONG ux_host_class_hid_field_physical; + ULONG ux_host_class_hid_field_logical; + ULONG ux_host_class_hid_field_application; + ULONG ux_host_class_hid_field_usage_page; + ULONG ux_host_class_hid_field_usage_min; + ULONG ux_host_class_hid_field_usage_max; + SLONG ux_host_class_hid_field_logical_min; + SLONG ux_host_class_hid_field_logical_max; + SLONG ux_host_class_hid_field_physical_min; + SLONG ux_host_class_hid_field_physical_max; + ULONG ux_host_class_hid_field_unit; + ULONG ux_host_class_hid_field_unit_expo; + ULONG ux_host_class_hid_field_report_type; + ULONG ux_host_class_hid_field_report_id; + ULONG ux_host_class_hid_field_report_offset; + ULONG ux_host_class_hid_field_report_size; + ULONG ux_host_class_hid_field_report_count; + ULONG ux_host_class_hid_field_value; + ULONG *ux_host_class_hid_field_usages; + ULONG ux_host_class_hid_field_number_usage; + ULONG *ux_host_class_hid_field_values; + ULONG ux_host_class_hid_field_number_values; + struct UX_HOST_CLASS_HID_REPORT + *ux_host_class_hid_field_report; + struct UX_HOST_CLASS_HID_FIELD_STRUCT + *ux_host_class_hid_field_next_field; +} UX_HOST_CLASS_HID_FIELD; + + +/* Define HID Class report structure. */ + +typedef struct UX_HOST_CLASS_HID_REPORT_STRUCT +{ + + ULONG ux_host_class_hid_report_id; + ULONG ux_host_class_hid_report_type; + struct UX_HOST_CLASS_HID_FIELD_STRUCT + *ux_host_class_hid_report_field; + ULONG ux_host_class_hid_report_number_item; + ULONG ux_host_class_hid_report_byte_length; + ULONG ux_host_class_hid_report_bit_length; + ULONG ux_host_class_hid_report_callback_flags; + VOID *ux_host_class_hid_report_callback_buffer; + ULONG ux_host_class_hid_report_callback_length; + VOID (*ux_host_class_hid_report_callback_function) (struct UX_HOST_CLASS_HID_REPORT_CALLBACK_STRUCT *); + struct UX_HOST_CLASS_HID_REPORT_STRUCT + *ux_host_class_hid_report_next_report; +} UX_HOST_CLASS_HID_REPORT; + + +/* Define HID main parser structure. */ + +typedef struct UX_HOST_CLASS_HID_PARSER_STRUCT +{ + + UX_HOST_CLASS_HID_GLOBAL_ITEM + ux_host_class_hid_parser_global; + UX_HOST_CLASS_HID_GLOBAL_ITEM + ux_host_class_hid_parser_global_pool[UX_HOST_CLASS_HID_MAX_GLOBAL]; + ULONG ux_host_class_hid_parser_number_global; + UX_HOST_CLASS_HID_LOCAL_ITEM + ux_host_class_hid_parser_local; + ULONG ux_host_class_hid_parser_application; + ULONG ux_host_class_hid_parser_collection[UX_HOST_CLASS_HID_MAX_COLLECTION]; + ULONG ux_host_class_hid_parser_number_collection; + ULONG ux_host_class_hid_parser_main_page; + ULONG ux_host_class_hid_parser_main_usage; + UX_HOST_CLASS_HID_REPORT + *ux_host_class_hid_parser_input_report; + UX_HOST_CLASS_HID_REPORT + *ux_host_class_hid_parser_output_report; + UX_HOST_CLASS_HID_REPORT + *ux_host_class_hid_parser_feature_report; +} UX_HOST_CLASS_HID_PARSER; + + +/* Define HID Class item analysis structure. */ + +typedef struct UX_HOST_CLASS_HID_ITEM_STRUCT +{ + + UCHAR ux_host_class_hid_item_report_type; + UCHAR ux_host_class_hid_item_report_tag; + USHORT ux_host_class_hid_item_report_length; + USHORT ux_host_class_hid_item_report_format; +} UX_HOST_CLASS_HID_ITEM; + + +/* Define HID Class instance structure. */ + +typedef struct UX_HOST_CLASS_HID_STRUCT +{ + + struct UX_HOST_CLASS_HID_STRUCT + *ux_host_class_hid_next_instance; + UX_HOST_CLASS *ux_host_class_hid_class; + UX_DEVICE *ux_host_class_hid_device; + UX_ENDPOINT *ux_host_class_hid_interrupt_endpoint; + UINT ux_host_class_hid_interrupt_endpoint_status; + UX_INTERFACE *ux_host_class_hid_interface; + ULONG ux_host_class_hid_state; + struct UX_HID_DESCRIPTOR_STRUCT + ux_host_class_hid_descriptor; + UX_HOST_CLASS_HID_PARSER + ux_host_class_hid_parser; + struct UX_HOST_CLASS_HID_CLIENT_STRUCT + *ux_host_class_hid_client; + TX_SEMAPHORE ux_host_class_hid_semaphore; +} UX_HOST_CLASS_HID; + + +/* Define HID Class client command format structure. */ + +typedef struct UX_HOST_CLASS_HID_CLIENT_COMMAND_STRUCT +{ + + UINT ux_host_class_hid_client_command_request; + VOID *ux_host_class_hid_client_command_container; + UX_HOST_CLASS_HID *ux_host_class_hid_client_command_instance; + ULONG ux_host_class_hid_client_command_page; + ULONG ux_host_class_hid_client_command_usage; +} UX_HOST_CLASS_HID_CLIENT_COMMAND; + + +/* Define HID Class report command structure. */ + +typedef struct UX_HOST_CLASS_HID_CLIENT_REPORT_STRUCT +{ + + UX_HOST_CLASS_HID_REPORT + *ux_host_class_hid_client_report; + ULONG *ux_host_class_hid_client_report_buffer; + ULONG ux_host_class_hid_client_report_length; + ULONG ux_host_class_hid_client_report_actual_length; + UINT ux_host_class_hid_client_report_flags; +} UX_HOST_CLASS_HID_CLIENT_REPORT; + + +/* Define HID Class client structure. */ + +typedef struct UX_HOST_CLASS_HID_CLIENT_STRUCT +{ + + ULONG ux_host_class_hid_client_status; + UCHAR ux_host_class_hid_client_name[UX_HOST_CLASS_HID_MAX_CLIENT_NAME_LENGTH + 1]; /* "+1" for string null-terminator */ + UINT (*ux_host_class_hid_client_handler) (struct UX_HOST_CLASS_HID_CLIENT_COMMAND_STRUCT *); + VOID *ux_host_class_hid_client_local_instance; +} UX_HOST_CLASS_HID_CLIENT; + +/* Define HID Class function prototypes. */ + +UINT _ux_host_class_hid_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_hid_client_register(UCHAR *hid_client_name, + UINT (*hid_client_handler)(struct UX_HOST_CLASS_HID_CLIENT_COMMAND_STRUCT *)); +UINT _ux_host_class_hid_client_search(UX_HOST_CLASS_HID *hid); +UINT _ux_host_class_hid_configure(UX_HOST_CLASS_HID *hid); +UINT _ux_host_class_hid_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_hid_descriptor_parse(UX_HOST_CLASS_HID *hid); +UINT _ux_host_class_hid_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_hid_field_decompress(UX_HOST_CLASS_HID_FIELD *hid_field, UCHAR *report_buffer, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report); +UINT _ux_host_class_hid_global_item_parse(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_ITEM *item, UCHAR *descriptor); +UINT _ux_host_class_hid_idle_get(UX_HOST_CLASS_HID *hid, USHORT *idle_time, USHORT report_id); +UINT _ux_host_class_hid_idle_set(UX_HOST_CLASS_HID *hid, USHORT idle_time, USHORT report_id); +UINT _ux_host_class_hid_instance_clean(UX_HOST_CLASS_HID *hid); +UINT _ux_host_class_hid_interrupt_endpoint_search(UX_HOST_CLASS_HID *hid); +ULONG _ux_host_class_hid_item_data_get(UCHAR *descriptor, UX_HOST_CLASS_HID_ITEM *item); +UINT _ux_host_class_hid_local_item_parse(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_ITEM *item, UCHAR *descriptor); +UINT _ux_host_class_hid_main_item_parse(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_ITEM *item, UCHAR *descriptor); +UINT _ux_host_class_hid_periodic_report_start(UX_HOST_CLASS_HID *hid); +UINT _ux_host_class_hid_periodic_report_stop(UX_HOST_CLASS_HID *hid); +UINT _ux_host_class_hid_report_add(UX_HOST_CLASS_HID *hid, UCHAR *descriptor, UX_HOST_CLASS_HID_ITEM *item); +UINT _ux_host_class_hid_report_callback_register(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_REPORT_CALLBACK *call_back); +UINT _ux_host_class_hid_report_compress(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report, + UCHAR *report_buffer, ULONG report_length); +UINT _ux_host_class_hid_report_decompress(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report, + UCHAR *report_buffer, ULONG report_length); +UINT _ux_host_class_hid_report_descriptor_get(UX_HOST_CLASS_HID *hid, ULONG length); +UINT _ux_host_class_hid_report_get(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report); +UINT _ux_host_class_hid_report_id_get(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_REPORT_GET_ID *report_id); +UINT _ux_host_class_hid_report_item_analyse(UCHAR *descriptor, UX_HOST_CLASS_HID_ITEM *item); +UINT _ux_host_class_hid_report_set(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report); +UINT _ux_host_class_hid_resources_free(UX_HOST_CLASS_HID *hid); +VOID _ux_host_class_hid_transfer_request_completed(UX_TRANSFER *transfer_request); + +/* Define HID Class API prototypes. */ + +#define ux_host_class_hid_client_register _ux_host_class_hid_client_register +#define ux_host_class_hid_client_search _ux_host_class_hid_client_search +#define ux_host_class_hid_descriptor_parse _ux_host_class_hid_descriptor_parse +#define ux_host_class_hid_entry _ux_host_class_hid_entry +#define ux_host_class_hid_idle_get _ux_host_class_hid_idle_get +#define ux_host_class_hid_idle_set _ux_host_class_hid_idle_set +#define ux_host_class_hid_periodic_report_start _ux_host_class_hid_periodic_report_start +#define ux_host_class_hid_periodic_report_stop _ux_host_class_hid_periodic_report_stop +#define ux_host_class_hid_report_add _ux_host_class_hid_report_add +#define ux_host_class_hid_report_callback_register _ux_host_class_hid_report_callback_register +#define ux_host_class_hid_report_descriptor_get _ux_host_class_hid_report_descriptor_get +#define ux_host_class_hid_report_get _ux_host_class_hid_report_get +#define ux_host_class_hid_report_id_get _ux_host_class_hid_report_id_get +#define ux_host_class_hid_report_set _ux_host_class_hid_report_set + +#endif + diff --git a/common/usbx_host_classes/inc/ux_host_class_hid_keyboard.h b/common/usbx_host_classes/inc/ux_host_class_hid_keyboard.h new file mode 100644 index 0000000..1a6a5d2 --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_hid_keyboard.h @@ -0,0 +1,219 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Keyboard Client */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_hid_keyboard.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX HID keyboard client. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_HID_KEYBOARD_H +#define UX_HOST_CLASS_HID_KEYBOARD_H + + +/* Define HID Keyboard Class constants. */ + +#define UX_HOST_CLASS_HID_KEYBOARD_BUFFER_LENGTH 128 +#define UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH 64 + +/* Each item in usage array takes 4 bytes. Check memory bytes calculation overflow here. */ +#if UX_OVERFLOW_CHECK_MULC_ULONG(UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH, 4) +#error UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH too large for memory allocation +#endif + +/* Define HID Keyboard Class LED keys. */ + +#define UX_HID_LED_KEY_CAPS_LOCK 0x39 +#define UX_HID_LED_KEY_NUM_LOCK 0x53 +#define UX_HID_LED_KEY_SCROLL_LOCK 0x47 + + +/* Define HID Keyboard Class Modifier Keys. */ + +#define UX_HID_MODIFIER_KEY_LEFT_CONTROL 0xe0 +#define UX_HID_MODIFIER_KEY_LEFT_SHIFT 0xe1 +#define UX_HID_MODIFIER_KEY_LEFT_ALT 0xe2 +#define UX_HID_MODIFIER_KEY_LEFT_GUI 0xe3 +#define UX_HID_MODIFIER_KEY_RIGHT_CONTROL 0xe4 +#define UX_HID_MODIFIER_KEY_RIGHT_SHIFT 0xe5 +#define UX_HID_MODIFIER_KEY_RIGHT_ALT 0xe6 +#define UX_HID_MODIFIER_KEY_RIGHT_GUI 0xe7 + + +/* Define HID Keyboard States. */ + +#define UX_HID_KEYBOARD_STATE_NUM_LOCK 0x0001 +#define UX_HID_KEYBOARD_STATE_CAPS_LOCK 0x0002 +#define UX_HID_KEYBOARD_STATE_SCROLL_LOCK 0x0004 +#define UX_HID_KEYBOARD_STATE_MASK_LOCK 0x0007 + +#define UX_HID_KEYBOARD_STATE_LEFT_SHIFT 0x0100 +#define UX_HID_KEYBOARD_STATE_RIGHT_SHIFT 0x0200 +#define UX_HID_KEYBOARD_STATE_SHIFT 0x0300 + +#define UX_HID_KEYBOARD_STATE_LEFT_ALT 0x0400 +#define UX_HID_KEYBOARD_STATE_RIGHT_ALT 0x0800 +#define UX_HID_KEYBOARD_STATE_ALT 0x0a00 + +#define UX_HID_KEYBOARD_STATE_LEFT_CTRL 0x1000 +#define UX_HID_KEYBOARD_STATE_RIGHT_CTRL 0x2000 +#define UX_HID_KEYBOARD_STATE_CTRL 0x3000 + +#define UX_HID_KEYBOARD_STATE_LEFT_GUI 0x4000 +#define UX_HID_KEYBOARD_STATE_RIGHT_GUI 0x8000 +#define UX_HID_KEYBOARD_STATE_GUI 0xa000 + +#define UX_HID_KEYBOARD_STATE_KEY_UP 0x10000 +#define UX_HID_KEYBOARD_STATE_FUNCTION 0x20000 + +/* Define HID keyboard generic equivalences. */ + +#define UX_HID_KEYBOARD_NO_KEY 0 +#define UX_HID_KEYBOARD_PHANTOM_STATE 0x01 +#define UX_HID_KEYBOARD_KEY_LETTER_A 0x04 +#define UX_HID_KEYBOARD_KEY_LETTER_Z 0x1D +#define UX_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE 0x54 +#define UX_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE 0x67 +#define UX_HID_KEYBOARD_KEYS_UPPER_RANGE 115 + +/* Define HID keyboard ioctl Functions. */ + +#define UX_HID_KEYBOARD_IOCTL_SET_LAYOUT 0 +#define UX_HID_KEYBOARD_IOCTL_DISABLE_KEYS_DECODE 1 +#define UX_HID_KEYBOARD_IOCTL_ENABLE_KEYS_DECODE 2 + +/* Define HID keyboard layout array. */ + +#define UX_HID_KEYBOARD_REGULAR_ARRAY_US \ + 0,0,0,0, \ + 'a','b','c','d','e','f','g','h','i','j','k','l','m','n', \ + 'o','p','q','r','s','t','u','v','w','x','y','z', \ + '1','2','3','4','5','6','7','8','9','0', \ + 0x0d,0x1b,0x08,0x07,0x20,'-','=','[',']', \ + '\\','#',';',0x27,'`',',','.','/',0xf0, \ + 0xbb,0xbc,0xbd,0xbe,0xbf,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6, \ + 0x00,0xf1,0x00,0xd2,0xc7,0xc9,0xd3,0xcf,0xd1,0xcd,0xcb,0xd0,0xc8,0xf2, \ + '/','*','-','+', \ + 0x0d,'1','2','3','4','5','6','7','8','9','0','.','\\',0x00,0x00,'=', \ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + +#define UX_HID_KEYBOARD_SHIFT_ARRAY_US \ + 0,0,0,0, \ + 'A','B','C','D','E','F','G','H','I','J','K','L','M','N', \ + 'O','P','Q','R','S','T','U','V','W','X','Y','Z', \ + '!','@','#','$','%','^','&','*','(',')', \ + 0x0d,0x1b,0x08,0x07,0x20,'_','+','{','}', \ + '|','~',':','"','~','<','>','?',0xf0, \ + 0xbb,0xbc,0xbd,0xbe,0xbf,0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6, \ + 0x00,0xf1,0x00,0xd2,0xc7,0xc9,0xd3,0xcf,0xd1,0xcd,0xcb,0xd0,0xc8,0xf2, \ + '/','*','-','+', \ + 0x0d,'1','2','3','4','5','6','7','8','9','0','.','\\',0x00,0x00,'=', \ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + +#define UX_HID_KEYBOARD_NUMLOCK_ON_ARRAY \ + '/','*','-','+', \ + 0x0d, \ + '1','2','3','4','5','6','7','8','9','0', \ + '.','\\',0x00,0x00,'=', + +#define UX_HID_KEYBOARD_NUMLOCK_OFF_ARRAY \ + '/','*','-','+', \ + 0x0d, \ + 0xcf,0xd0,0xd1,0xcb,'5',0xcd,0xc7,0xc8,0xc9,0xd2, \ + 0xd3,'\\',0x00,0x00,'=', + +/* Define HID Keyboard layout (key mapping) structure. */ + +typedef struct UX_HOST_CLASS_HID_KEYBOARD_LAYOUT_STRUCT +{ + + UCHAR *ux_host_class_hid_keyboard_layout_regular_array; + UCHAR *ux_host_class_hid_keyboard_layout_shift_array; + UCHAR *ux_host_class_hid_keyboard_layout_numlock_on_array; + UCHAR *ux_host_class_hid_keyboard_layout_numlock_off_array; + ULONG ux_host_class_hid_keyboard_layout_keys_upper_range; + ULONG ux_host_class_hid_keyboard_layout_letters_lower_range; + ULONG ux_host_class_hid_keyboard_layout_letters_upper_range; + ULONG ux_host_class_hid_keyboard_layout_keypad_lower_range; + ULONG ux_host_class_hid_keyboard_layout_keypad_upper_range; +} UX_HOST_CLASS_HID_KEYBOARD_LAYOUT; + +/* Define HID Keyboard Class structure. */ + +typedef struct UX_HOST_CLASS_HID_KEYBOARD_STRUCT +{ + + ULONG ux_host_class_hid_keyboard_state; + UCHAR *ux_host_class_hid_keyboard_key_state; + ULONG ux_host_class_hid_keyboard_key_count; + UX_HOST_CLASS_HID *ux_host_class_hid_keyboard_hid; + USHORT ux_host_class_hid_keyboard_id; + TX_THREAD ux_host_class_hid_keyboard_thread; + TX_SEMAPHORE ux_host_class_hid_keyboard_semaphore; + ULONG ux_host_class_hid_keyboard_alternate_key_state; + ULONG ux_host_class_hid_keyboard_led_mask; + VOID *ux_host_class_hid_keyboard_thread_stack; + ULONG *ux_host_class_hid_keyboard_usage_array; + ULONG *ux_host_class_hid_keyboard_usage_array_head; + ULONG *ux_host_class_hid_keyboard_usage_array_tail; + UX_HOST_CLASS_HID_KEYBOARD_LAYOUT *ux_host_class_hid_keyboard_layout; + ULONG ux_host_class_hid_keyboard_keys_decode_disable; +} UX_HOST_CLASS_HID_KEYBOARD; + +/* Define HID Keyboard Class function prototypes. */ + +VOID _ux_host_class_hid_keyboard_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK *callback); +UINT _ux_host_class_hid_keyboard_activate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command); +UINT _ux_host_class_hid_keyboard_deactivate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command); +UINT _ux_host_class_hid_keyboard_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command); +VOID _ux_host_class_hid_keyboard_thread(ULONG thread_entry); +UINT _ux_host_class_hid_keyboard_key_get(UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance, + ULONG *keyboard_key, ULONG *keyboard_state); +UINT _ux_host_class_hid_keyboard_ioctl(UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance, + ULONG ioctl_function, VOID *parameter); + +/* Define HID Keyboard Class API prototypes. */ + +#define ux_host_class_hid_keyboard_entry _ux_host_class_hid_keyboard_entry +#define ux_host_class_hid_keyboard_key_get _ux_host_class_hid_keyboard_key_get +#define ux_host_class_hid_keyboard_ioctl _ux_host_class_hid_keyboard_ioctl + +#endif + diff --git a/common/usbx_host_classes/inc/ux_host_class_hid_mouse.h b/common/usbx_host_classes/inc/ux_host_class_hid_mouse.h new file mode 100644 index 0000000..363611e --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_hid_mouse.h @@ -0,0 +1,107 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Mouse Client Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_hid_mouse.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX HID mouse class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_HID_MOUSE_H +#define UX_HOST_CLASS_HID_MOUSE_H + + +/* Define HID Mouse Class constants. */ + +#define UX_HOST_CLASS_HID_MOUSE_BUFFER_LENGTH 128 +#define UX_HOST_CLASS_HID_MOUSE_USAGE_ARRAY_LENGTH 64 + +#define UX_HOST_CLASS_HID_MOUSE_BUTTON_1 0x00090001 +#define UX_HOST_CLASS_HID_MOUSE_BUTTON_2 0x00090002 +#define UX_HOST_CLASS_HID_MOUSE_BUTTON_3 0x00090003 + +#define UX_HOST_CLASS_HID_MOUSE_AXIS_X 0x00010030 +#define UX_HOST_CLASS_HID_MOUSE_AXIS_Y 0x00010031 + + +#define UX_HOST_CLASS_HID_MOUSE_BUTTON_1_PRESSED 0x01 +#define UX_HOST_CLASS_HID_MOUSE_BUTTON_2_PRESSED 0x02 +#define UX_HOST_CLASS_HID_MOUSE_BUTTON_3_PRESSED 0x04 + +#define UX_HOST_CLASS_HID_MOUSE_WHEEL 0x00010038 + +/* Define HID Mouse Class structure. */ + +typedef struct UX_HOST_CLASS_HID_MOUSE_STRUCT +{ + + ULONG ux_host_class_hid_mouse_state; + UX_HOST_CLASS_HID *ux_host_class_hid_mouse_hid; + USHORT ux_host_class_hid_mouse_id; + SLONG ux_host_class_hid_mouse_x_position; + SLONG ux_host_class_hid_mouse_y_position; + ULONG ux_host_class_hid_mouse_buttons; + SLONG ux_host_class_hid_mouse_wheel; + + +} UX_HOST_CLASS_HID_MOUSE; + +/* Define HID Mouse Class function prototypes. */ + +UINT _ux_host_class_hid_mouse_activate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command); +VOID _ux_host_class_hid_mouse_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK *callback); +UINT _ux_host_class_hid_mouse_deactivate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command); +UINT _ux_host_class_hid_mouse_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command); +UINT _ux_host_class_hid_mouse_buttons_get(UX_HOST_CLASS_HID_MOUSE *mouse_instance, + ULONG *mouse_buttons); +UINT _ux_host_class_hid_mouse_position_get(UX_HOST_CLASS_HID_MOUSE *mouse_instance, + SLONG *mouse_x_position, + SLONG *mouse_y_position); +UINT _ux_host_class_hid_mouse_wheel_get(UX_HOST_CLASS_HID_MOUSE *mouse_instance, + SLONG *mouse_wheel_movement); + +/* Define HID Mouse Class API prototypes. */ + +#define ux_host_class_hid_mouse_entry _ux_host_class_hid_mouse_entry +#define ux_host_class_hid_mouse_buttons_get _ux_host_class_hid_mouse_buttons_get +#define ux_host_class_hid_mouse_position_get _ux_host_class_hid_mouse_position_get +#define ux_host_class_hid_mouse_wheel_get _ux_host_class_hid_mouse_wheel_get + +#endif diff --git a/common/usbx_host_classes/inc/ux_host_class_hid_remote_control.h b/common/usbx_host_classes/inc/ux_host_class_hid_remote_control.h new file mode 100644 index 0000000..11d006f --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_hid_remote_control.h @@ -0,0 +1,87 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Remote Control Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_hid_remote_control.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX HID remote control class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_HID_REMOTE_CONTROL_H +#define UX_HOST_CLASS_HID_REMOTE_CONTROL_H + + +/* Define HID Remote Control Class constants. */ + +#define UX_HOST_CLASS_HID_REMOTE_CONTROL_BUFFER_LENGTH 128 +#define UX_HOST_CLASS_HID_REMOTE_CONTROL_USAGE_ARRAY_LENGTH 64 + +/* Each item in usage array takes 4 bytes. Check memory bytes calculation overflow here. */ +#if UX_OVERFLOW_CHECK_MULC_ULONG(UX_HOST_CLASS_HID_REMOTE_CONTROL_USAGE_ARRAY_LENGTH, 4) +#error UX_HOST_CLASS_HID_REMOTE_CONTROL_USAGE_ARRAY_LENGTH is too large for memory allocation, please check +#endif + +/* Define HID Remote Control Class structure. */ + +typedef struct UX_HOST_CLASS_HID_REMOTE_CONTROL_STRUCT +{ + + ULONG ux_host_class_hid_remote_control_state; + UX_HOST_CLASS_HID *ux_host_class_hid_remote_control_hid; + ULONG *ux_host_class_hid_remote_control_usage_array; + ULONG *ux_host_class_hid_remote_control_usage_array_head; + ULONG *ux_host_class_hid_remote_control_usage_array_tail; +} UX_HOST_CLASS_HID_REMOTE_CONTROL; + +/* Define HID Remote Control Class function prototypes. */ + +VOID _ux_host_class_hid_remote_control_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK *callback); +UINT _ux_host_class_hid_remote_control_activate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command); +UINT _ux_host_class_hid_remote_control_deactivate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command); +UINT _ux_host_class_hid_remote_control_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command); +UINT _ux_host_class_hid_remote_control_usage_get(UX_HOST_CLASS_HID_REMOTE_CONTROL *remote_control_instance, ULONG *usage, ULONG *value); + +/* Define HID Keyboard Class API prototypes. */ + +#define ux_host_class_hid_remote_control_entry _ux_host_class_hid_remote_control_entry +#define ux_host_class_hid_remote_control_usage_get _ux_host_class_hid_remote_control_usage_get + +#endif + diff --git a/common/usbx_host_classes/inc/ux_host_class_hub.h b/common/usbx_host_classes/inc/ux_host_class_hub.h new file mode 100644 index 0000000..47a77d5 --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_hub.h @@ -0,0 +1,198 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_hub.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX HUB class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_HUB_H +#define UX_HOST_CLASS_HUB_H + + +/* Define HUB Class constants. */ + +#define UX_HOST_CLASS_HUB_CLASS 9 +#define UX_HOST_CLASS_HUB_PROTOCOL_FS 0 +#define UX_HOST_CLASS_HUB_PROTOCOL_SINGLE_TT 1 +#define UX_HOST_CLASS_HUB_PROTOCOL_MULTIPLE_TT 2 + + +/* Define HUB Class descriptor field constants. */ + +#define UX_HOST_CLASS_HUB_GANG_POWER_SWITCHING 0x00 +#define UX_HOST_CLASS_HUB_INDIVIDUAL_POWER_SWITCHING 0x01 +#define UX_HOST_CLASS_HUB_NO_POWER_SWITCHING 0x02 + +#define UX_HOST_CLASS_HUB_COMPOUND_DEVICE 0x04 + +#define UX_HOST_CLASS_HUB_GLOBAL_OVERCURRENT 0x00 +#define UX_HOST_CLASS_HUB_INDIVIDUAL_OVERCURRENT 0x08 +#define UX_HOST_CLASS_HUB_NO_OVERCURRENT 0x10 + + +/* Define HUB Class command constants. */ + +#define UX_HOST_CLASS_HUB_GET_STATUS 0x00 +#define UX_HOST_CLASS_HUB_CLEAR_FEATURE 0x01 +#define UX_HOST_CLASS_HUB_GET_STATE 0x02 +#define UX_HOST_CLASS_HUB_SET_FEATURE 0x03 +#define UX_HOST_CLASS_HUB_GET_DESCRIPTOR 0x06 +#define UX_HOST_CLASS_HUB_SET_DESCRIPTOR 0x07 + + +/* Define HUB Class set_feature command constants. */ + +#define UX_HOST_CLASS_HUB_PORT_CONNECTION 0x00 +#define UX_HOST_CLASS_HUB_PORT_ENABLE 0x01 +#define UX_HOST_CLASS_HUB_PORT_SUSPEND 0x02 +#define UX_HOST_CLASS_HUB_PORT_OVER_CURRENT 0x03 +#define UX_HOST_CLASS_HUB_PORT_RESET 0x04 +#define UX_HOST_CLASS_HUB_PORT_POWER 0x08 +#define UX_HOST_CLASS_HUB_PORT_LOW_SPEED 0x09 +#define UX_HOST_CLASS_HUB_C_PORT_CONNECTION 0x10 +#define UX_HOST_CLASS_HUB_C_PORT_ENABLE 0x11 +#define UX_HOST_CLASS_HUB_C_PORT_SUSPEND 0x12 +#define UX_HOST_CLASS_HUB_C_PORT_OVER_CURRENT 0x13 +#define UX_HOST_CLASS_HUB_C_PORT_RESET 0x14 + + +/* Define HUB Class port status constants. */ + +#define UX_HOST_CLASS_HUB_PORT_STATUS_CONNECTION 0x0001 +#define UX_HOST_CLASS_HUB_PORT_STATUS_ENABLE 0x0002 +#define UX_HOST_CLASS_HUB_PORT_STATUS_SUSPEND 0x0004 +#define UX_HOST_CLASS_HUB_PORT_STATUS_OVER_CURRENT 0x0008 +#define UX_HOST_CLASS_HUB_PORT_STATUS_RESET 0x0010 +#define UX_HOST_CLASS_HUB_PORT_STATUS_POWER 0x0100 +#define UX_HOST_CLASS_HUB_PORT_STATUS_LOW_SPEED 0x0200 +#define UX_HOST_CLASS_HUB_PORT_STATUS_HIGH_SPEED 0x0400 + + +/* Define HUB Class port change constants. */ + +#define UX_HOST_CLASS_HUB_PORT_CHANGE_CONNECTION 0x00001 +#define UX_HOST_CLASS_HUB_PORT_CHANGE_ENABLE 0x00002 +#define UX_HOST_CLASS_HUB_PORT_CHANGE_SUSPEND 0x00004 +#define UX_HOST_CLASS_HUB_PORT_CHANGE_OVER_CURRENT 0x00008 +#define UX_HOST_CLASS_HUB_PORT_CHANGE_RESET 0x00010 + + +/* Define HUB Class other constants. */ + +#define UX_HOST_CLASS_HUB_ENABLE_RETRY_COUNT 3 +#define UX_HOST_CLASS_HUB_ENABLE_RETRY_DELAY 100 +#define UX_HOST_CLASS_HUB_ENUMERATION_RETRY 3 +#define UX_HOST_CLASS_HUB_ENUMERATION_DEBOUNCE_DELAY 100 +#define UX_HOST_CLASS_HUB_ENUMERATION_RESET_RECOVERY_DELAY 10 +#define UX_HOST_CLASS_HUB_ENUMERATION_RETRY_DELAY 300 + + +/* Define HUB Descriptor. */ +#define UX_HUB_DESCRIPTOR_ENTRIES 8 +#define UX_HUB_DESCRIPTOR_LENGTH 9 + +/* Define HUB Class structure. */ + +#define UX_MAX_HUB_PORTS 15 + +typedef struct UX_HUB_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bNbPorts; + ULONG wHubCharacteristics; + ULONG bPwrOn2PwrGood; + ULONG bHubContrCurrent; + ULONG bDeviceRemovable; + ULONG bPortPwrCtrlMask; +} UX_HUB_DESCRIPTOR; + + +/* Define HUB Class instance structure. */ + +typedef struct UX_HOST_CLASS_HUB_STRUCT +{ + + struct UX_HOST_CLASS_HUB_STRUCT + *ux_host_class_hub_next_instance; + UX_HOST_CLASS *ux_host_class_hub_class; + UX_DEVICE *ux_host_class_hub_device; + UX_ENDPOINT *ux_host_class_hub_interrupt_endpoint; + UX_INTERFACE *ux_host_class_hub_interface; + UINT ux_host_class_hub_instance_status; + UINT ux_host_class_hub_state; + UINT ux_host_class_hub_enumeration_retry_count; + UINT ux_host_class_hub_change_semaphore; + struct UX_HUB_DESCRIPTOR_STRUCT + ux_host_class_hub_descriptor; + UINT ux_host_class_hub_port_state; + UINT ux_host_class_hub_port_power; + +} UX_HOST_CLASS_HUB; + + +/* Define HUB Class function prototypes. */ + +UINT _ux_host_class_hub_activate(UX_HOST_CLASS_COMMAND *command); +VOID _ux_host_class_hub_change_detect(VOID); +UINT _ux_host_class_hub_change_process(UX_HOST_CLASS_HUB *hub); +UINT _ux_host_class_hub_configure(UX_HOST_CLASS_HUB *hub); +UINT _ux_host_class_hub_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_hub_descriptor_get(UX_HOST_CLASS_HUB *hub); +UINT _ux_host_class_hub_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_hub_feature(UX_HOST_CLASS_HUB *hub, UINT port, UINT command, UINT function); +UINT _ux_host_class_hub_hub_change_process(UX_HOST_CLASS_HUB *hub); +UINT _ux_host_class_hub_interrupt_endpoint_start(UX_HOST_CLASS_HUB *hub); +VOID _ux_host_class_hub_port_change_connection_process(UX_HOST_CLASS_HUB *hub, UINT port, UINT port_status); +VOID _ux_host_class_hub_port_change_enable_process(UX_HOST_CLASS_HUB *hub, UINT port, UINT port_status); +VOID _ux_host_class_hub_port_change_over_current_process(UX_HOST_CLASS_HUB *hub, UINT port, UINT port_status); +UINT _ux_host_class_hub_port_change_process(UX_HOST_CLASS_HUB *hub, UINT port); +VOID _ux_host_class_hub_port_change_reset_process(UX_HOST_CLASS_HUB *hub, UINT port, UINT port_status); +VOID _ux_host_class_hub_port_change_suspend_process(UX_HOST_CLASS_HUB *hub, UINT port, UINT port_status); +UINT _ux_host_class_hub_port_reset(UX_HOST_CLASS_HUB *hub, UINT port); +UINT _ux_host_class_hub_ports_power(UX_HOST_CLASS_HUB *hub); +UINT _ux_host_class_hub_status_get(UX_HOST_CLASS_HUB *hub, UINT port, USHORT *port_status, USHORT *port_change); +VOID _ux_host_class_hub_transfer_request_completed(UX_TRANSFER *transfer_request); + +#endif + diff --git a/common/usbx_host_classes/inc/ux_host_class_pima.h b/common/usbx_host_classes/inc/ux_host_class_pima.h new file mode 100644 index 0000000..009415c --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_pima.h @@ -0,0 +1,570 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_cdc_acm.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX PIMA class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_PIMA_H +#define UX_HOST_CLASS_PIMA_H + +/* Define PIMA Class constants. */ + +#define UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT 300000 +#define UX_HOST_CLASS_PIMA_CLASS 0x06 +#define UX_HOST_CLASS_PIMA_SUBCLASS 0X01 +#define UX_HOST_CLASS_PIMA_PROTOCOL 0X01 +#define UX_HOST_CLASS_PIMA_CS_INTERFACE 0x24 +#define UX_HOST_CLASS_PIMA_MAGIC_NUMBER 0x50494D41 +#define UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH 256 +#define UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH 256 +#define UX_HOST_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH 64 +#define UX_HOST_CLASS_PIMA_MAX_STORAGE_IDS 64 +#define UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH (UX_HOST_CLASS_PIMA_MAX_STORAGE_IDS * sizeof(ULONG)) +#define UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH_ASSERT UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(ULONG), UX_HOST_CLASS_PIMA_MAX_STORAGE_IDS), UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH_calc_ovf) +#define UX_HOST_CLASS_PIMA_MAX_PAYLOAD 1024 +#define UX_HOST_CLASS_PIMA_ZLP_NONE 0 +#define UX_HOST_CLASS_PIMA_ZLP_IN 1 +#define UX_HOST_CLASS_PIMA_ZLP_OUT 2 + +/* Define PIMA data phases. */ + +#define UX_HOST_CLASS_PIMA_DATA_PHASE_NONE 0 +#define UX_HOST_CLASS_PIMA_DATA_PHASE_IN 1 +#define UX_HOST_CLASS_PIMA_DATA_PHASE_OUT 2 + +/* Define PIMA session states. */ + +#define UX_HOST_CLASS_PIMA_SESSION_STATE_CLOSED 0 +#define UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED 1 + +/* Define PIMA object and thumb states. */ + +#define UX_HOST_CLASS_PIMA_OBJECT_STATE_CLOSED 0 +#define UX_HOST_CLASS_PIMA_OBJECT_STATE_OPENED 1 + +/* Define PIMA object and thumb transfer status. */ + +#define UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_INACTIVE 0 +#define UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ACTIVE 1 +#define UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_COMPLETED 2 +#define UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED 3 + +/* Define PIMA Cancel Request equivalences. */ + +#define UX_HOST_CLASS_PIMA_REQUEST_CANCEL_COMMAND 0x64 +#define UX_HOST_CLASS_PIMA_REQUEST_CANCEL_DATA_LENGTH 0x06 +#define UX_HOST_CLASS_PIMA_REQUEST_CANCEL_CODE 0x04001 +#define UX_HOST_CLASS_PIMA_REQUEST_CANCEL_OFFSET_CODE 0x00 +#define UX_HOST_CLASS_PIMA_REQUEST_CANCEL_OFFSET_TRANSACTION_ID 0x02 + +/* Define PIMA Reset Request equivalences. */ + +#define UX_HOST_CLASS_PIMA_REQUEST_RESET_DEVICE 0x66 + +/* Define PIMA Status Request equivalences. */ + +#define UX_HOST_CLASS_PIMA_REQUEST_STATUS_COMMAND 0x67 +#define UX_HOST_CLASS_PIMA_REQUEST_STATUS_DATA_LENGTH 0x40 +#define UX_HOST_CLASS_PIMA_REQUEST_STATUS_OFFSET_LENGTH 0x00 +#define UX_HOST_CLASS_PIMA_REQUEST_STATUS_OFFSET_CODE 0x02 +#define UX_HOST_CLASS_PIMA_REQUEST_STATUS_COMMAND_COUNTER 16 +#define UX_HOST_CLASS_PIMA_REQUEST_STATUS_COMMAND_DELAY 1000 + +/* Define PIMA command container type. */ + +#define UX_HOST_CLASS_PIMA_CT_UNDEFINED 0x00 +#define UX_HOST_CLASS_PIMA_CT_COMMAND_BLOCK 0x01 +#define UX_HOST_CLASS_PIMA_CT_DATA_BLOCK 0x02 +#define UX_HOST_CLASS_PIMA_CT_RESPONSE_BLOCK 0x03 +#define UX_HOST_CLASS_PIMA_CT_EVENT_BLOCK 0x04 + +/* Define PIMA Extended Event Data Request payload Format. */ + +#define UX_HOST_CLASS_PIMA_EEDR_EVENT_CODE 0x00 +#define UX_HOST_CLASS_PIMA_EEDR_TRANSACTION_ID 0x02 +#define UX_HOST_CLASS_PIMA_EEDR_NUMBER_PARAMETERS 0x06 +#define UX_HOST_CLASS_PIMA_EEDR_SIZE_PARAMETER 0x08 + +/* Define PIMA Device Status Data Format. */ + +#define UX_HOST_CLASS_PIMA_DSD_LENGTH 0x00 +#define UX_HOST_CLASS_PIMA_DSD_CODE 0x02 +#define UX_HOST_CLASS_PIMA_DSD_PARAMETER 0x04 + +/* Define PIMA Command Header Format. */ + +#define UX_HOST_CLASS_PIMA_COMMAND_HEADER_LENGTH 0x00 +#define UX_HOST_CLASS_PIMA_COMMAND_HEADER_TYPE 0x04 +#define UX_HOST_CLASS_PIMA_COMMAND_HEADER_CODE 0x06 +#define UX_HOST_CLASS_PIMA_COMMAND_HEADER_TRANSACTION_ID 0x08 +#define UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_1 0x0C +#define UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_2 0x10 +#define UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_3 0x14 +#define UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_4 0x18 +#define UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_5 0x1C + +#define UX_HOST_CLASS_PIMA_COMMAND_HEADER_SIZE 0x0C +#define UX_HOST_CLASS_PIMA_CONTAINER_SIZE 0x40 +#define UX_HOST_CLASS_PIMA_ALL_HEADER_SIZE 0x20 + +/* Define PIMA Data Header Format. */ + +#define UX_HOST_CLASS_PIMA_DATA_HEADER_LENGTH 0x00 +#define UX_HOST_CLASS_PIMA_DATA_HEADER_TYPE 0x04 +#define UX_HOST_CLASS_PIMA_DATA_HEADER_CODE 0x06 +#define UX_HOST_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID 0x08 +#define UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE 0x0C + + +/* Define PIMA Response Header Format. */ + +#define UX_HOST_CLASS_PIMA_RESPONSE_HEADER_LENGTH 0x00 +#define UX_HOST_CLASS_PIMA_RESPONSE_HEADER_TYPE 0x04 +#define UX_HOST_CLASS_PIMA_RESPONSE_HEADER_CODE 0x06 +#define UX_HOST_CLASS_PIMA_RESPONSE_HEADER_TRANSACTION_ID 0x08 +#define UX_HOST_CLASS_PIMA_RESPONSE_HEADER_PARAMETER_1 0x0C +#define UX_HOST_CLASS_PIMA_RESPONSE_HEADER_PARAMETER_2 0x10 +#define UX_HOST_CLASS_PIMA_RESPONSE_HEADER_PARAMETER_3 0x14 +#define UX_HOST_CLASS_PIMA_RESPONSE_HEADER_PARAMETER_4 0x18 +#define UX_HOST_CLASS_PIMA_RESPONSE_HEADER_PARAMETER_5 0x1C + +#define UX_HOST_CLASS_PIMA_RESPONSE_HEADER_SIZE 0x20 + +/* Define PIMA Asynchronous Event Interrupt Data Format. */ + +#define UX_HOST_CLASS_PIMA_AEI_DATA_LENGTH 0x00 +#define UX_HOST_CLASS_PIMA_AEI_TYPE 0x04 +#define UX_HOST_CLASS_PIMA_AEI_EVENT_CODE 0x06 +#define UX_HOST_CLASS_PIMA_AEI_TRANSACTION_ID 0x08 +#define UX_HOST_CLASS_PIMA_AEI_PARAMETER_1 0x0C +#define UX_HOST_CLASS_PIMA_AEI_PARAMETER_2 0x10 +#define UX_HOST_CLASS_PIMA_AEI_PARAMETER_3 0x14 +#define UX_HOST_CLASS_PIMA_AEI_MAX_LENGTH 0x18 + +/* Define PIMA Operation Commands. */ + +#define UX_HOST_CLASS_PIMA_OC_UNDEFINED 0x1000 +#define UX_HOST_CLASS_PIMA_OC_GET_DEVICE_INFO 0x1001 +#define UX_HOST_CLASS_PIMA_OC_OPEN_SESSION 0x1002 +#define UX_HOST_CLASS_PIMA_OC_CLOSE_SESSION 0x1003 +#define UX_HOST_CLASS_PIMA_OC_GET_STORAGE_IDS 0x1004 +#define UX_HOST_CLASS_PIMA_OC_GET_STORAGE_INFO 0x1005 +#define UX_HOST_CLASS_PIMA_OC_GET_NUM_OBJECTS 0x1006 +#define UX_HOST_CLASS_PIMA_OC_GET_OBJECT_HANDLES 0x1007 +#define UX_HOST_CLASS_PIMA_OC_GET_OBJECT_INFO 0x1008 +#define UX_HOST_CLASS_PIMA_OC_GET_OBJECT 0x1009 +#define UX_HOST_CLASS_PIMA_OC_GET_THUMB 0x100A +#define UX_HOST_CLASS_PIMA_OC_DELETE_OBJECT 0x100B +#define UX_HOST_CLASS_PIMA_OC_SEND_OBJECT_INFO 0x100C +#define UX_HOST_CLASS_PIMA_OC_SEND_OBJECT 0x100D +#define UX_HOST_CLASS_PIMA_OC_INITIATE_CAPTURE 0x100E +#define UX_HOST_CLASS_PIMA_OC_FORMAT_STORE 0x100F +#define UX_HOST_CLASS_PIMA_OC_RESET_DEVICE 0x1010 +#define UX_HOST_CLASS_PIMA_OC_SELF_TEST 0x1011 +#define UX_HOST_CLASS_PIMA_OC_SET_OBJECT_PROTECTION 0x1012 +#define UX_HOST_CLASS_PIMA_OC_POWER_DOWN 0x1013 +#define UX_HOST_CLASS_PIMA_OC_GET_DEVICE_PROP_DESC 0x1014 +#define UX_HOST_CLASS_PIMA_OC_GET_DEVICE_PROP_VALUE 0x1015 +#define UX_HOST_CLASS_PIMA_OC_SET_DEVICE_PROP_VALUE 0x1016 +#define UX_HOST_CLASS_PIMA_OC_RESET_DEVICE_PROP_VALUE 0x1017 +#define UX_HOST_CLASS_PIMA_OC_TERMINATE_OPEN_CAPTURE 0x1018 +#define UX_HOST_CLASS_PIMA_OC_MOVE_OBJECT 0x1019 +#define UX_HOST_CLASS_PIMA_OC_COPY_OBJECT 0x101A +#define UX_HOST_CLASS_PIMA_OC_GET_PARTIAL_OBJECT 0x101B +#define UX_HOST_CLASS_PIMA_OC_INITIATE_OPEN_CAPTURE 0x101C + +/* Define PIMA Response Codes. */ + +#define UX_HOST_CLASS_PIMA_RC_UNDEFINED 0x2000 +#define UX_HOST_CLASS_PIMA_RC_OK 0x2001 +#define UX_HOST_CLASS_PIMA_RC_GENERAL_ERROR 0x2002 +#define UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN 0x2003 +#define UX_HOST_CLASS_PIMA_RC_INVALID_TRANSACTION_ID 0x2004 +#define UX_HOST_CLASS_PIMA_RC_OPERATION_NOT_SUPPORTED 0x2005 +#define UX_HOST_CLASS_PIMA_RC_PARAMETER_NOT_SUPPORTED 0x2006 +#define UX_HOST_CLASS_PIMA_RC_INCOMPLETE_TRANSFER 0x2007 +#define UX_HOST_CLASS_PIMA_RC_INVALID_STORAGE_ID 0x2008 +#define UX_HOST_CLASS_PIMA_RC_INVALID_OBJECT_HANDLE 0x2009 +#define UX_HOST_CLASS_PIMA_RC_DEVICE_PROP_NOT_SUPPORTED 0x200A +#define UX_HOST_CLASS_PIMA_RC_INVALID_OBJECT_FORMAT_CODE 0x200B +#define UX_HOST_CLASS_PIMA_RC_STORE_FULL 0x200C +#define UX_HOST_CLASS_PIMA_RC_OBJECT_WRITE_PROTECTED 0x200D +#define UX_HOST_CLASS_PIMA_RC_STORE_READ_ONLY 0x200E +#define UX_HOST_CLASS_PIMA_RC_ACCESS_DENIED 0x200F +#define UX_HOST_CLASS_PIMA_RC_NO_THUMBNAIL_PRESENT 0x2010 +#define UX_HOST_CLASS_PIMA_RC_SELF_TEST_FAILED 0x2011 +#define UX_HOST_CLASS_PIMA_RC_PARTIAL_DELETION 0x2012 +#define UX_HOST_CLASS_PIMA_RC_STORE_NOT_AVAILABLE 0x2013 +#define UX_HOST_CLASS_PIMA_RC_FORMAT_UNSUPPORTED 0x2014 +#define UX_HOST_CLASS_PIMA_RC_NO_VALID_OBJECT_INFO 0x2015 +#define UX_HOST_CLASS_PIMA_RC_INVALID_CODE_FORMAT 0x2016 +#define UX_HOST_CLASS_PIMA_RC_UNKNOWN_VENDOR_CODE 0x2017 +#define UX_HOST_CLASS_PIMA_RC_CAPTURE_ALREADY_TERMINATED 0x2018 +#define UX_HOST_CLASS_PIMA_RC_DEVICE_BUSY 0x2019 +#define UX_HOST_CLASS_PIMA_RC_INVALID_PARENT_OBJECT 0x201A +#define UX_HOST_CLASS_PIMA_RC_INVALID_DEVICE_PROP_FORMAT 0x201B +#define UX_HOST_CLASS_PIMA_RC_INVALID_DEVICE_PROP_VALUE 0x201C +#define UX_HOST_CLASS_PIMA_RC_INVALID_PARAMETER 0x201D +#define UX_HOST_CLASS_PIMA_RC_SESSION_ALREADY_OPENED 0x201E +#define UX_HOST_CLASS_PIMA_RC_TRANSACTION_CANCELED 0x201F +#define UX_HOST_CLASS_PIMA_RC_DESTINATION_UNSUPPORTED 0x2020 +#define UX_HOST_CLASS_PIMA_RC_OBJECT_ALREADY_OPENED 0x2021 +#define UX_HOST_CLASS_PIMA_RC_OBJECT_ALREADY_CLOSED 0x2022 +#define UX_HOST_CLASS_PIMA_RC_OBJECT_NOT_OPENED 0x2023 + +/* Define PIMA Event Codes. */ + +#define UX_HOST_CLASS_PIMA_EC_UNDEFINED 0x4000 +#define UX_HOST_CLASS_PIMA_EC_CANCEL_TRANSACTION 0x4001 +#define UX_HOST_CLASS_PIMA_EC_OBJECT_ADDED 0x4002 +#define UX_HOST_CLASS_PIMA_EC_OBJECT_REMOVED 0x4003 +#define UX_HOST_CLASS_PIMA_EC_STORE_ADDED 0x4004 +#define UX_HOST_CLASS_PIMA_EC_STORE_REMOVED 0x4005 +#define UX_HOST_CLASS_PIMA_EC_DEVICE_PROP_CHANGED 0x4006 +#define UX_HOST_CLASS_PIMA_EC_OBJECT_INFO_CHANGED 0x4007 +#define UX_HOST_CLASS_PIMA_EC_DEVICE_INFO_CHANGED 0x4008 +#define UX_HOST_CLASS_PIMA_EC_REQUEST_OBJECT_TRANSFER 0x4009 +#define UX_HOST_CLASS_PIMA_EC_STORE_FULL 0x400A +#define UX_HOST_CLASS_PIMA_EC_DEVICE_RESET 0x400B +#define UX_HOST_CLASS_PIMA_EC_STORAGE_INFO_CHANGED 0x400C +#define UX_HOST_CLASS_PIMA_EC_CAPTURE_COMPLETE 0x400D +#define UX_HOST_CLASS_PIMA_EC_UNREPORTED_STATUS 0x400E + +/* Define PIMA Object Format Codes. */ + +#define UX_HOST_CLASS_PIMA_OFC_UNDEFINED 0x3000 +#define UX_HOST_CLASS_PIMA_OFC_ASSOCIATION 0x3001 +#define UX_HOST_CLASS_PIMA_OFC_SCRIPT 0x3002 +#define UX_HOST_CLASS_PIMA_OFC_EXECUTABLE 0x3003 +#define UX_HOST_CLASS_PIMA_OFC_TEXT 0x3004 +#define UX_HOST_CLASS_PIMA_OFC_HTML 0x3005 +#define UX_HOST_CLASS_PIMA_OFC_DPOF 0x3006 +#define UX_HOST_CLASS_PIMA_OFC_AIFF 0x3007 +#define UX_HOST_CLASS_PIMA_OFC_WAV 0x3008 +#define UX_HOST_CLASS_PIMA_OFC_MP3 0x3009 +#define UX_HOST_CLASS_PIMA_OFC_AVI 0x300A +#define UX_HOST_CLASS_PIMA_OFC_MPEG 0x300B +#define UX_HOST_CLASS_PIMA_OFC_ASF 0x300C +#define UX_HOST_CLASS_PIMA_OFC_QT 0x300D +#define UX_HOST_CLASS_PIMA_OFC_EXIF_JPEG 0x3801 +#define UX_HOST_CLASS_PIMA_OFC_TIFF_EP 0x3802 +#define UX_HOST_CLASS_PIMA_OFC_FLASHPIX 0x3803 +#define UX_HOST_CLASS_PIMA_OFC_BMP 0x3804 +#define UX_HOST_CLASS_PIMA_OFC_CIFF 0x3805 +#define UX_HOST_CLASS_PIMA_OFC_GIF 0x3807 +#define UX_HOST_CLASS_PIMA_OFC_JFIF 0x3808 +#define UX_HOST_CLASS_PIMA_OFC_PCD 0x3809 +#define UX_HOST_CLASS_PIMA_OFC_PICT 0x380A +#define UX_HOST_CLASS_PIMA_OFC_PNG 0x380B +#define UX_HOST_CLASS_PIMA_OFC_TIFF 0x380D +#define UX_HOST_CLASS_PIMA_OFC_TIFF_IT 0x380E +#define UX_HOST_CLASS_PIMA_OFC_JP2 0x380F +#define UX_HOST_CLASS_PIMA_OFC_JPX 0x3810 + +/* Define PIMA Object Protection Status Values. */ + +#define UX_HOST_CLASS_PIMA_OPS_NO_PROTECTION 0x0000 +#define UX_HOST_CLASS_PIMA_OPS_READ_ONLY 0x0001 + +/* Define PIMA Storage Types Codes. */ + +#define UX_HOST_CLASS_PIMA_STC_UNDEFINED 0x0000 +#define UX_HOST_CLASS_PIMA_STC_FIXED_ROM 0x0001 +#define UX_HOST_CLASS_PIMA_STC_REMOVABLE_ROM 0x0002 +#define UX_HOST_CLASS_PIMA_STC_FIXED_RAM 0x0003 +#define UX_HOST_CLASS_PIMA_STC_REMOVABLE_RAM 0x0004 + +/* Define PIMA File System Types Codes. */ + +#define UX_HOST_CLASS_PIMA_FSTC_UNDEFINED 0x0000 +#define UX_HOST_CLASS_PIMA_FSTC_GENERIC_FLAT 0x0001 +#define UX_HOST_CLASS_PIMA_FSTC_GENERIC_HIERARCHICAL 0x0002 +#define UX_HOST_CLASS_PIMA_FSTC_DCF 0x0003 + +/* Define PIMA event info structure. */ + +typedef struct UX_HOST_CLASS_PIMA_EVENT_STRUCT +{ + struct UX_HOST_CLASS_PIMA_SESSION_STRUCT + *ux_host_class_pima_event_session; + struct UX_HOST_CLASS_PIMA_STRUCT + *ux_host_class_pima_event_pima_instance; + ULONG ux_host_class_pima_event_code; + ULONG ux_host_class_pima_event_session_id; + ULONG ux_host_class_pima_event_transaction_id; + ULONG ux_host_class_pima_event_parameter_1; + ULONG ux_host_class_pima_event_parameter_2; + ULONG ux_host_class_pima_event_parameter_3; + +} UX_HOST_CLASS_PIMA_EVENT; + +/* Define PIMA structure. */ + +typedef struct UX_HOST_CLASS_PIMA_STRUCT +{ + + struct UX_HOST_CLASS_PIMA_STRUCT + *ux_host_class_pima_next_instance; + UX_HOST_CLASS *ux_host_class_pima_class; + UX_DEVICE *ux_host_class_pima_device; + UX_INTERFACE *ux_host_class_pima_interface; + UX_ENDPOINT *ux_host_class_pima_bulk_out_endpoint; + UX_ENDPOINT *ux_host_class_pima_bulk_in_endpoint; + UX_ENDPOINT *ux_host_class_pima_interrupt_endpoint; + UINT ux_host_class_pima_state; + ULONG ux_host_class_pima_transaction_id; + ULONG ux_host_class_pima_operation_code; + ULONG ux_host_class_pima_event_code; + ULONG ux_host_class_pima_event_transaction_id; + ULONG ux_host_class_pima_event_session; + ULONG ux_host_class_pima_event_parameter_1; + ULONG ux_host_class_pima_event_parameter_2; + ULONG ux_host_class_pima_event_parameter_3; + UCHAR *ux_host_class_pima_event_buffer; + UCHAR *ux_host_class_pima_event_buffer_current_offset; + ULONG ux_host_class_pima_event_buffer_current_length; + ULONG ux_host_class_pima_event_buffer_expected_length; + struct UX_HOST_CLASS_PIMA_SESSION_STRUCT + *ux_host_class_pima_session; + UCHAR *ux_host_class_pima_container; + TX_SEMAPHORE ux_host_class_pima_semaphore; + VOID *ux_host_class_pima_application; + ULONG ux_host_class_pima_zlp_flag; + +} UX_HOST_CLASS_PIMA; + +/* Define PIMA Session structure. */ + +typedef struct UX_HOST_CLASS_PIMA_SESSION_STRUCT +{ + + ULONG ux_host_class_pima_session_magic; + ALIGN_TYPE ux_host_class_pima_session_id; + ULONG ux_host_class_pima_session_state; + struct UX_HOST_CLASS_PIMA_STRUCT + *ux_host_class_pima_session_pima_instance; + ULONG ux_host_class_pima_session_nb_storage_ids; + ULONG ux_host_class_pima_session_nb_objects; + VOID (*ux_host_class_pima_session_event_callback)(struct UX_HOST_CLASS_PIMA_EVENT_STRUCT *pima_event); + +} UX_HOST_CLASS_PIMA_SESSION; + + +/* Define PIMA command structure. */ + +typedef struct UX_HOST_CLASS_PIMA_COMMAND_STRUCT +{ + + ULONG ux_host_class_pima_command_nb_parameters; + ULONG ux_host_class_pima_command_operation_code; + ULONG ux_host_class_pima_command_parameter_1; + ULONG ux_host_class_pima_command_parameter_2; + ULONG ux_host_class_pima_command_parameter_3; + ULONG ux_host_class_pima_command_parameter_4; + ULONG ux_host_class_pima_command_parameter_5; + +} UX_HOST_CLASS_PIMA_COMMAND; + +/* Define PIMA object info structure. */ + +typedef struct UX_HOST_CLASS_PIMA_OBJECT_STRUCT +{ + + ULONG ux_host_class_pima_object_storage_id; + ULONG ux_host_class_pima_object_format; + ULONG ux_host_class_pima_object_protection_satus; + ULONG ux_host_class_pima_object_compressed_size; + ULONG ux_host_class_pima_object_thumb_format; + ULONG ux_host_class_pima_object_thumb_compressed_size; + ULONG ux_host_class_pima_object_thumb_pix_width; + ULONG ux_host_class_pima_object_thumb_pix_height; + ULONG ux_host_class_pima_object_image_pix_width; + ULONG ux_host_class_pima_object_image_pix_height; + ULONG ux_host_class_pima_object_image_bit_depth; + ULONG ux_host_class_pima_object_parent_object; + ULONG ux_host_class_pima_object_association_type; + ULONG ux_host_class_pima_object_association_desc; + ULONG ux_host_class_pima_object_sequence_number; + UCHAR ux_host_class_pima_object_filename[UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH]; + UCHAR ux_host_class_pima_object_capture_date[UX_HOST_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH]; + UCHAR ux_host_class_pima_object_modification_date[UX_HOST_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH]; + UCHAR ux_host_class_pima_object_keywords[UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH]; + ULONG ux_host_class_pima_object_state; + ULONG ux_host_class_pima_object_offset; + ULONG ux_host_class_pima_object_transfer_status; + ULONG ux_host_class_pima_object_handle_id; + ULONG ux_host_class_pima_object_length; + UCHAR *ux_host_class_pima_object_buffer; + +} UX_HOST_CLASS_PIMA_OBJECT; + +/* Define PIMA Object decompaction structure. */ + +#define UX_HOST_CLASS_PIMA_OBJECT_MAX_LENGTH 512 +#define UX_HOST_CLASS_PIMA_OBJECT_VARIABLE_OFFSET 52 +#define UX_HOST_CLASS_PIMA_OBJECT_ENTRIES 15 + +/* Define PIMA device info structure. */ + +typedef struct UX_HOST_CLASS_PIMA_DEVICE_STRUCT +{ + + ULONG ux_host_class_pima_device_standard_version; + ULONG ux_host_class_pima_device_vendor_extension_id; + ULONG ux_host_class_pima_device_vendor_extension_version; + UCHAR ux_host_class_pima_device_vendor_extension_desc[UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH]; + ULONG ux_host_class_pima_device_functional_mode; + UCHAR ux_host_class_pima_device_operations_supported[UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH]; + UCHAR ux_host_class_pima_device_events_supported[UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH]; + UCHAR ux_host_class_pima_device_properties_supported[UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH]; + UCHAR ux_host_class_pima_device_capture_formats[UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH]; + UCHAR ux_host_class_pima_device_image_formats[UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH]; + UCHAR ux_host_class_pima_device_manufacturer[UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH]; + UCHAR ux_host_class_pima_device_model[UX_HOST_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH]; + UCHAR ux_host_class_pima_device_version[UX_HOST_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH]; + UCHAR ux_host_class_pima_device_serial_number[UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH]; + +} UX_HOST_CLASS_PIMA_DEVICE; + +/* Define PIMA Device decompaction structure. */ + +#define UX_HOST_CLASS_PIMA_DEVICE_MAX_LENGTH 512 +#define UX_HOST_CLASS_PIMA_DEVICE_STANDARD_VERSION 0 +#define UX_HOST_CLASS_PIMA_DEVICE_VENDOR_EXTENSION_ID 2 +#define UX_HOST_CLASS_PIMA_DEVICE_VENDOR_EXTENSION_VERSION 6 +#define UX_HOST_CLASS_PIMA_DEVICE_VENDOR_EXTENSION_DESC 8 + +/* Define PIMA storage info structure. */ + +typedef struct UX_HOST_CLASS_PIMA_STORAGE_STRUCT +{ + + ULONG ux_host_class_pima_storage_type; + ULONG ux_host_class_pima_storage_file_system_type; + ULONG ux_host_class_pima_storage_access_capability; + ULONG ux_host_class_pima_storage_max_capacity_low; + ULONG ux_host_class_pima_storage_max_capacity_high; + ULONG ux_host_class_pima_storage_free_space_bytes_low; + ULONG ux_host_class_pima_storage_free_space_bytes_high; + ULONG ux_host_class_pima_storage_free_space_images; + UCHAR ux_host_class_pima_storage_description[UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH]; + UCHAR ux_host_class_pima_storage_volume_label[UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH]; + +} UX_HOST_CLASS_PIMA_STORAGE; + +/* Define PIMA storage decompaction structure. */ + +#define UX_HOST_CLASS_PIMA_STORAGE_MAX_LENGTH 512 +#define UX_HOST_CLASS_PIMA_STORAGE_VARIABLE_OFFSET 26 +#define UX_HOST_CLASS_PIMA_STORAGE_ENTRIES 8 + +/* Define Pima Class function prototypes. */ + +UINT _ux_host_class_pima_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_pima_configure(UX_HOST_CLASS_PIMA *cdc_acm); +UINT _ux_host_class_pima_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_pima_endpoints_get(UX_HOST_CLASS_PIMA *cdc_acm); +UINT _ux_host_class_pima_entry(UX_HOST_CLASS_COMMAND *command); +VOID _ux_host_class_pima_notification(UX_TRANSFER *transfer_request); +UINT _ux_host_class_pima_command(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_COMMAND *command, + ULONG direction, UCHAR *data_buffer, ULONG data_length, + ULONG max_payload_length); +UINT _ux_host_class_pima_device_reset(UX_HOST_CLASS_PIMA *pima); +UINT _ux_host_class_pima_num_objects_get(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, ULONG storage_id, + ULONG object_format_code); +UINT _ux_host_class_pima_object_copy(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, ULONG object_handle, + ULONG storage_id, ULONG parent_object_handle); +UINT _ux_host_class_pima_object_delete(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, ULONG object_handle); +UINT _ux_host_class_pima_object_get(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object, + UCHAR *object_buffer, ULONG object_buffer_length, ULONG *object_actual_length); +UINT _ux_host_class_pima_object_handles_get(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG *object_handles_array, ULONG object_handles_length, ULONG storage_id, ULONG object_format_code, ULONG object_handle_association); +UINT _ux_host_class_pima_object_info_get(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object); +UINT _ux_host_class_pima_object_info_send(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, ULONG storage_id, ULONG parent_object_id, + UX_HOST_CLASS_PIMA_OBJECT *object); +UINT _ux_host_class_pima_object_move(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, ULONG object_handle, ULONG storage_id, ULONG parent_object_handle); +UINT _ux_host_class_pima_object_send(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, UX_HOST_CLASS_PIMA_OBJECT *object, + UCHAR *object_buffer, ULONG object_buffer_length); +UINT _ux_host_class_pima_read(UX_HOST_CLASS_PIMA *pima, UCHAR *data_pointer, ULONG data_length, ULONG max_payload_length); +UINT _ux_host_class_pima_session_close(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session); +UINT _ux_host_class_pima_session_open(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session); +UINT _ux_host_class_pima_storage_ids_get(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, ULONG *storage_ids_array, ULONG storage_id_length); +UINT _ux_host_class_pima_storage_info_get(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, ULONG storage_id, UX_HOST_CLASS_PIMA_STORAGE *storage); +UINT _ux_host_class_pima_thumb_get(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object, + UCHAR *thumb_buffer, ULONG thumb_buffer_length, ULONG *thumb_actual_length); +UINT _ux_host_class_pima_write(UX_HOST_CLASS_PIMA *pima, UCHAR *data_pointer, ULONG data_length, ULONG operation_code, ULONG max_payload_length); +UINT _ux_host_class_pima_request_cancel(UX_HOST_CLASS_PIMA *pima); +UINT _ux_host_class_pima_object_transfer_abort(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object); +UINT _ux_host_class_pima_object_close(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object); +UINT _ux_host_class_pima_object_open(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object); +UINT _ux_host_class_pima_device_info_get(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_DEVICE *pima_device); + +/* Define Device PIMA Class API prototypes. */ + +#define ux_host_class_pima_entry _ux_host_class_pima_entry +#define ux_host_class_pima_device_info_get _ux_host_class_pima_device_info_get +#define ux_host_class_pima_object_info_send _ux_host_class_pima_object_info_send +#define ux_host_class_pima_object_info_get _ux_host_class_pima_object_info_get +#define ux_host_class_pima_object_open _ux_host_class_pima_object_open +#define ux_host_class_pima_object_get _ux_host_class_pima_object_get +#define ux_host_class_pima_thumb_get _ux_host_class_pima_thumb_get +#define ux_host_class_pima_object_send _ux_host_class_pima_object_send +#define ux_host_class_pima_object_delete _ux_host_class_pima_object_delete +#define ux_host_class_pima_object_transfer_abort _ux_host_class_pima_object_transfer_abort +#define ux_host_class_pima_object_close _ux_host_class_pima_object_close +#define ux_host_class_pima_num_objects_get _ux_host_class_pima_num_objects_get +#define ux_host_class_pima_session_open _ux_host_class_pima_session_open +#define ux_host_class_pima_session_close _ux_host_class_pima_session_close +#define ux_host_class_pima_storage_ids_get _ux_host_class_pima_storage_ids_get +#define ux_host_class_pima_storage_info_get _ux_host_class_pima_storage_info_get +#define ux_host_class_pima_object_handles_get _ux_host_class_pima_object_handles_get +#define ux_host_class_pima_num_objects_get _ux_host_class_pima_num_objects_get + +#endif diff --git a/common/usbx_host_classes/inc/ux_host_class_printer.h b/common/usbx_host_classes/inc/ux_host_class_printer.h new file mode 100644 index 0000000..7cdf4b7 --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_printer.h @@ -0,0 +1,117 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_printer.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX printer class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_PRINTER_H +#define UX_HOST_CLASS_PRINTER_H + + +/* Define Printer Class constants. */ + +#define UX_HOST_CLASS_PRINTER_CLASS_TRANSFER_TIMEOUT 300000 +#define UX_HOST_CLASS_PRINTER_CLASS 7 +#define UX_HOST_CLASS_PRINTER_SUBCLASS 1 +#define UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL 2 +#define UX_HOST_CLASS_PRINTER_GET_STATUS 1 +#define UX_HOST_CLASS_PRINTER_SOFT_RESET 2 +#define UX_HOST_CLASS_PRINTER_STATUS_LENGTH 4 +#define UX_HOST_CLASS_PRINTER_DESCRIPTOR_LENGTH 1024 +#define UX_HOST_CLASS_PRINTER_GET_DEVICE_ID 0 +#define UX_HOST_CLASS_PRINTER_NAME_LENGTH 64 + + +/* Define Printer Class 1284 descriptor tag constants. */ + +#define UX_HOST_CLASS_PRINTER_TAG_DESCRIPTION "DESCRIPTION:" +#define UX_HOST_CLASS_PRINTER_TAG_DES "DES:" + + +/* Define Printer Class string constants. */ + +#define UX_HOST_CLASS_PRINTER_GENERIC_NAME "USB PRINTER" + +/* Define Printer Class structure. */ + +typedef struct UX_HOST_CLASS_PRINTER_STRUCT +{ + + struct UX_HOST_CLASS_PRINTER_STRUCT + *ux_host_class_printer_next_instance; + UX_HOST_CLASS *ux_host_class_printer_class; + UX_DEVICE *ux_host_class_printer_device; + UX_INTERFACE *ux_host_class_printer_interface; + UX_ENDPOINT *ux_host_class_printer_bulk_out_endpoint; + UX_ENDPOINT *ux_host_class_printer_bulk_in_endpoint; + UINT ux_host_class_printer_state; + UCHAR ux_host_class_printer_name[UX_HOST_CLASS_PRINTER_NAME_LENGTH]; + TX_SEMAPHORE ux_host_class_printer_semaphore; +} UX_HOST_CLASS_PRINTER; + + +/* Define Printer Class function prototypes. */ + +UINT _ux_host_class_printer_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_printer_configure(UX_HOST_CLASS_PRINTER *printer); +UINT _ux_host_class_printer_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_printer_endpoints_get(UX_HOST_CLASS_PRINTER *printer); +UINT _ux_host_class_printer_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_printer_name_get(UX_HOST_CLASS_PRINTER *printer); +UINT _ux_host_class_printer_read (UX_HOST_CLASS_PRINTER *printer, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_printer_soft_reset(UX_HOST_CLASS_PRINTER *printer); +UINT _ux_host_class_printer_status_get(UX_HOST_CLASS_PRINTER *printer, ULONG *printer_status); +UINT _ux_host_class_printer_write(UX_HOST_CLASS_PRINTER *printer, UCHAR * data_pointer, + ULONG requested_length, ULONG *actual_length); + +/* Define Printer Class API prototypes. */ + +#define ux_host_class_printer_activate _ux_host_class_printer_activate +#define ux_host_class_printer_name_get _ux_host_class_printer_name_get +#define ux_host_class_printer_read _ux_host_class_printer_read +#define ux_host_class_printer_soft_reset _ux_host_class_printer_soft_reset +#define ux_host_class_printer_status_get _ux_host_class_printer_status_get +#define ux_host_class_printer_write _ux_host_class_printer_write + +#endif diff --git a/common/usbx_host_classes/inc/ux_host_class_prolific.h b/common/usbx_host_classes/inc/ux_host_class_prolific.h new file mode 100644 index 0000000..79b4918 --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_prolific.h @@ -0,0 +1,293 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PROLIFIC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_prolific.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX PROLIFIC class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_PROLIFIC_H +#define UX_HOST_CLASS_PROLIFIC_H + +/* Define PROLIFIC Class constants. */ + +#define UX_HOST_CLASS_PROLIFIC_DEVICE_INIT_DELAY (1 * UX_PERIODIC_RATE) +#define UX_HOST_CLASS_PROLIFIC_CLASS_TRANSFER_TIMEOUT 300000 +#define UX_HOST_CLASS_PROLIFIC_SETUP_BUFFER_SIZE 16 +#define UX_HOST_CLASS_PROLIFIC_DEVICE_PRESENT 1 +#define UX_HOST_CLASS_PROLIFIC_DEVICE_NOT_PRESENT 0 +#define UX_HOST_CLASS_PROLIFIC_DEVICE_STATE_OFFSET 8 +#define UX_HOST_CLASS_PROLIFIC_DEVICE_STATE_MASK 0x7F +#define UX_HOST_CLASS_PROLIFIC_DEVICE_TYPE_0 0 +#define UX_HOST_CLASS_PROLIFIC_DEVICE_TYPE_1 1 +#define UX_HOST_CLASS_PROLIFIC_DEVICE_TYPE_HX 2 +#define UX_HOST_CLASS_PROLIFIC_VENDOR_READ_REQUEST 1 +#define UX_HOST_CLASS_PROLIFIC_VENDOR_WRITE_REQUEST 1 + +/* Define PROLIFIC Class descriptor subtypes in functional descriptors. */ +#define UX_HOST_CLASS_PROLIFIC_HEADER_DESCRIPTOR 0X00 +#define UX_HOST_CLASS_PROLIFIC_CALL_MANAGEMENT_DESCRIPTOR 0X01 +#define UX_HOST_CLASS_PROLIFIC_ABSTRACT_CONTROL_MGT_DESCRIPTOR 0X02 +#define UX_HOST_CLASS_PROLIFIC_DIRECT_LINE_MGT_DESCRIPTOR 0X03 +#define UX_HOST_CLASS_PROLIFIC_TELEPHONE_RINGER_DESCRIPTOR 0X04 +#define UX_HOST_CLASS_PROLIFIC_REPORT_CAPABILITY_DESCRIPTOR 0X05 +#define UX_HOST_CLASS_PROLIFIC_UNION_DESCRIPTOR 0X06 +#define UX_HOST_CLASS_PROLIFIC_COUNTRY_SELECTION_DESCRIPTOR 0X07 +#define UX_HOST_CLASS_PROLIFIC_TELEPHONE_OPERATIONAL_DESCRIPTOR 0X08 +#define UX_HOST_CLASS_PROLIFIC_USB_TERMINAL_DESCRIPTOR 0X09 + +/* Define PROLIFIC Class call management descriptors. */ +#define UX_HOST_CLASS_PROLIFIC_CALL_MANAGEMENT_CAPABILITIES 0x03 +#define UX_HOST_CLASS_PROLIFIC_CALL_MANAGEMENT_DCM 0x01 +#define UX_HOST_CLASS_PROLIFIC_CALL_MANAGEMENT_DCI 0x02 + +/* Define PROLIFIC command request values. */ + +#define UX_HOST_CLASS_PROLIFIC_REQ_SEND_ENCAPSULATED_COMMAND 0x00 +#define UX_HOST_CLASS_PROLIFIC_REQ_GET_ENCAPSULATED_COMMAND 0x01 +#define UX_HOST_CLASS_PROLIFIC_REQ_SET_COMM_FEATURE 0x02 +#define UX_HOST_CLASS_PROLIFIC_REQ_GET_COMM_FEATURE 0x03 +#define UX_HOST_CLASS_PROLIFIC_REQ_CLEAR_COMM_FEATURE 0x04 +#define UX_HOST_CLASS_PROLIFIC_REQ_SET_AUX_LINE_STATE 0x10 +#define UX_HOST_CLASS_PROLIFIC_REQ_SET_HOOK_STATE 0x11 +#define UX_HOST_CLASS_PROLIFIC_REQ_PULSE_SETUP 0x12 +#define UX_HOST_CLASS_PROLIFIC_REQ_SEND_PULSE 0x13 +#define UX_HOST_CLASS_PROLIFIC_REQ_SET_PUSLE_TIME 0x14 +#define UX_HOST_CLASS_PROLIFIC_REQ_RING_AUX_JACK 0x15 +#define UX_HOST_CLASS_PROLIFIC_REQ_SET_LINE_CODING 0x20 +#define UX_HOST_CLASS_PROLIFIC_REQ_GET_LINE_CODING 0x21 +#define UX_HOST_CLASS_PROLIFIC_REQ_SET_LINE_STATE 0x22 +#define UX_HOST_CLASS_PROLIFIC_REQ_SEND_BREAK 0x23 +#define UX_HOST_CLASS_PROLIFIC_REQ_SET_RINGER_PARMS 0x30 +#define UX_HOST_CLASS_PROLIFIC_REQ_GET_RINGER_PARMS 0x31 +#define UX_HOST_CLASS_PROLIFIC_REQ_SET_OPERATION_PARMS 0x32 +#define UX_HOST_CLASS_PROLIFIC_REQ_GET_OPERATION_PARMS 0x33 +#define UX_HOST_CLASS_PROLIFIC_REQ_SET_LINE_PARMS 0x34 +#define UX_HOST_CLASS_PROLIFIC_REQ_GET_LINE_PARMS 0x35 + +/* Define PROLIFIC line output control values. */ + +#define UX_HOST_CLASS_PROLIFIC_CTRL_DTR 0x01 +#define UX_HOST_CLASS_PROLIFIC_CTRL_RTS 0x02 + +/* Define PROLIFIC line input control values. */ + +#define UX_HOST_CLASS_PROLIFIC_CTRL_DCD 0x01 +#define UX_HOST_CLASS_PROLIFIC_CTRL_DSR 0x02 +#define UX_HOST_CLASS_PROLIFIC_CTRL_BRK 0x04 +#define UX_HOST_CLASS_PROLIFIC_CTRL_RI 0x08 + +#define UX_HOST_CLASS_PROLIFIC_CTRL_FRAMING 0x10 +#define UX_HOST_CLASS_PROLIFIC_CTRL_PARITY 0x20 +#define UX_HOST_CLASS_PROLIFIC_CTRL_OVERRUN 0x40 + +#define UX_HOST_CLASS_PROLIFIC_COMMAND_EEPROM_READ 0x8484 +#define UX_HOST_CLASS_PROLIFIC_COMMAND_EEPROM_WRITE 0x0404 +#define UX_HOST_CLASS_PROLIFIC_COMMAND_EEPROM_ADDRESS 0x8383 +#define UX_HOST_CLASS_PROLIFIC_COMMAND_REG_CONFIGURE 0x0002 +#define UX_HOST_CLASS_PROLIFIC_COMMAND_PIPE1_RESET 0x0008 +#define UX_HOST_CLASS_PROLIFIC_COMMAND_PIPE2_RESET 0x0009 + +/* Define PROLIFIC Class packet equivalences. */ + +#define UX_HOST_CLASS_PROLIFIC_PACKET_SIZE 128 + +/* Define PROLIFIC default values. */ + +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_DEFAULT_RATE 19200 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_DEFAULT_DATA_BIT 8 + +/* Define PROLIFIC line coding definitions. */ + +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_STOP_BIT_0 0 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_STOP_BIT_15 1 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_STOP_BIT_2 2 + +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_PARITY_NONE 0 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_PARITY_ODD 1 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_PARITY_EVEN 2 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_PARITY_MARK 3 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_PARITY_SPACE 4 + +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_LENGTH 7 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_RATE 0 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_STOP_BIT 4 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_PARITY 5 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_DATA_BIT 6 + +/* Define PROLIFIC line state definitions. */ + +#define UX_HOST_CLASS_PROLIFIC_LINE_STATE_STOP_BIT_0 0 +#define UX_HOST_CLASS_PROLIFIC_LINE_CODING_STOP_BIT_15 1 + +/* Define PROLIFIC IOCTL Functions. */ + +#define UX_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_CODING 0 +#define UX_HOST_CLASS_PROLIFIC_IOCTL_GET_LINE_CODING 1 +#define UX_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_STATE 2 +#define UX_HOST_CLASS_PROLIFIC_IOCTL_SEND_BREAK 3 +#define UX_HOST_CLASS_PROLIFIC_IOCTL_PURGE 4 +#define UX_HOST_CLASS_PROLIFIC_IOCTL_ABORT_IN_PIPE 5 +#define UX_HOST_CLASS_PROLIFIC_IOCTL_ABORT_OUT_PIPE 6 +#define UX_HOST_CLASS_PROLIFIC_IOCTL_REPORT_DEVICE_STATUS_CHANGE 7 +#define UX_HOST_CLASS_PROLIFIC_IOCTL_GET_DEVICE_STATUS 8 + +/* Define PROLIFIC Reception States. */ + +#define UX_HOST_CLASS_PROLIFIC_RECEPTION_STATE_STOPPED 0 +#define UX_HOST_CLASS_PROLIFIC_RECEPTION_STATE_STARTED 1 +#define UX_HOST_CLASS_PROLIFIC_RECEPTION_STATE_IN_TRANSFER 2 + + +/* Define PROLIFIC Class instance structure. */ + +typedef struct UX_HOST_CLASS_PROLIFIC_STRUCT +{ + struct UX_HOST_CLASS_PROLIFIC_STRUCT + *ux_host_class_prolific_next_instance; + UX_HOST_CLASS *ux_host_class_prolific_class; + UX_DEVICE *ux_host_class_prolific_device; + UX_ENDPOINT *ux_host_class_prolific_bulk_in_endpoint; + UX_ENDPOINT *ux_host_class_prolific_bulk_out_endpoint; + UX_ENDPOINT *ux_host_class_prolific_interrupt_endpoint; + UX_INTERFACE *ux_host_class_prolific_interface; + UINT ux_host_class_prolific_instance_status; + UINT ux_host_class_prolific_state; + TX_SEMAPHORE ux_host_class_prolific_semaphore; + ULONG ux_host_class_prolific_notification_count; + ULONG ux_host_class_prolific_device_state; + VOID (*ux_host_class_prolific_device_status_change_callback)(struct UX_HOST_CLASS_PROLIFIC_STRUCT *prolific, + ULONG device_state); + + ULONG ux_host_class_prolific_version; + UCHAR ux_host_class_prolific_device_type; + struct UX_HOST_CLASS_PROLIFIC_RECEPTION_STRUCT + *ux_host_class_prolific_reception; + +} UX_HOST_CLASS_PROLIFIC; + + +/* Define PROLIFIC reception structure. */ + +typedef struct UX_HOST_CLASS_PROLIFIC_RECEPTION_STRUCT +{ + + ULONG ux_host_class_prolific_reception_state; + ULONG ux_host_class_prolific_reception_block_size; + UCHAR *ux_host_class_prolific_reception_data_buffer; + ULONG ux_host_class_prolific_reception_data_buffer_size; + UCHAR *ux_host_class_prolific_reception_data_head; + UCHAR *ux_host_class_prolific_reception_data_tail; + VOID (*ux_host_class_prolific_reception_callback)(struct UX_HOST_CLASS_PROLIFIC_STRUCT *prolific, + UINT status, + UCHAR *reception_buffer, + ULONG reception_size); + +} UX_HOST_CLASS_PROLIFIC_RECEPTION; + +/* Define PROLIFIC Line Coding IOCTL structure. */ + +typedef struct UX_HOST_CLASS_PROLIFIC_LINE_CODING_STRUCT +{ + + ULONG ux_host_class_prolific_line_coding_dter; + ULONG ux_host_class_prolific_line_coding_stop_bit; + ULONG ux_host_class_prolific_line_coding_parity; + ULONG ux_host_class_prolific_line_coding_data_bits; + +} UX_HOST_CLASS_PROLIFIC_LINE_CODING; + +/* Define PROLIFIC Line State IOCTL structure. */ + +typedef struct UX_HOST_CLASS_PROLIFIC_LINE_STATE_STRUCT +{ + + ULONG ux_host_class_prolific_line_state_rts; + ULONG ux_host_class_prolific_line_state_dtr; + +} UX_HOST_CLASS_PROLIFIC_LINE_STATE; + +/* Define PROLIFIC Line break IOCTL structure. */ + +typedef struct UX_HOST_CLASS_PROLIFIC_LINE_BREAK_STRUCT +{ + + ULONG ux_host_class_prolific_line_break; + +} UX_HOST_CLASS_PROLIFIC_LINE_BREAK; + + +/* Define Prolific Class function prototypes. */ + +UINT _ux_host_class_prolific_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_prolific_configure(UX_HOST_CLASS_PROLIFIC *prolific); +UINT _ux_host_class_prolific_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_prolific_endpoints_get(UX_HOST_CLASS_PROLIFIC *prolific); +UINT _ux_host_class_prolific_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_prolific_read (UX_HOST_CLASS_PROLIFIC *prolific, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_prolific_write(UX_HOST_CLASS_PROLIFIC *prolific, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_prolific_ioctl(UX_HOST_CLASS_PROLIFIC *prolific, ULONG request, + VOID *parameter); +UINT _ux_host_class_prolific_command(UX_HOST_CLASS_PROLIFIC *prolific, ULONG command, + ULONG value, UCHAR *data_buffer, ULONG data_length); +VOID _ux_host_class_prolific_transfer_request_completed(UX_TRANSFER *transfer_request); +UINT _ux_host_class_prolific_reception_stop (UX_HOST_CLASS_PROLIFIC *prolific, + UX_HOST_CLASS_PROLIFIC_RECEPTION *prolific_reception); +UINT _ux_host_class_prolific_reception_start (UX_HOST_CLASS_PROLIFIC *prolific, + UX_HOST_CLASS_PROLIFIC_RECEPTION *prolific_reception); + +VOID _ux_host_class_prolific_reception_callback (UX_TRANSFER *transfer_request); +UINT _ux_host_class_prolific_setup(UX_HOST_CLASS_PROLIFIC *prolific); + +/* Define Prolific Class API prototypes. */ + +#define ux_host_class_prolific_entry _ux_host_class_prolific_entry +#define ux_host_class_prolific_read _ux_host_class_prolific_read +#define ux_host_class_prolific_write _ux_host_class_prolific_write +#define ux_host_class_prolific_ioctl _ux_host_class_prolific_ioctl +#define ux_host_class_prolific_command _ux_host_class_prolific_command +#define ux_host_class_prolific_reception_stop _ux_host_class_prolific_reception_stop +#define ux_host_class_prolific_reception_start _ux_host_class_prolific_reception_start +#define ux_host_class_prolific_setup _ux_host_class_prolific_setup + +#endif diff --git a/common/usbx_host_classes/inc/ux_host_class_storage.h b/common/usbx_host_classes/inc/ux_host_class_storage.h new file mode 100644 index 0000000..afe000d --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_storage.h @@ -0,0 +1,451 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_storage.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX storage class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_STORAGE_H +#define UX_HOST_CLASS_STORAGE_H + + +/* Include the FileX API. */ +#include "fx_api.h" + +/* Define User configurable Storage Class constants. */ + +#ifndef UX_MAX_HOST_LUN +#define UX_MAX_HOST_LUN 1 +#endif + +#ifndef UX_HOST_CLASS_STORAGE_MAX_MEDIA +#define UX_HOST_CLASS_STORAGE_MAX_MEDIA 1 +#endif + +#ifndef UX_HOST_CLASS_STORAGE_MEMORY_BUFFER_SIZE +#define UX_HOST_CLASS_STORAGE_MEMORY_BUFFER_SIZE (1024) +#endif + +#ifndef UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE +#define UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE (1024) +#endif + +#ifndef UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE +#define UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE UX_THREAD_STACK_SIZE +#endif + +/* Define Storage Class constants. */ + +#define UX_HOST_CLASS_STORAGE_DEVICE_INIT_DELAY (200) +#define UX_HOST_CLASS_STORAGE_THREAD_SLEEP_TIME (2000) +#define UX_HOST_CLASS_STORAGE_INSTANCE_SHUTDOWN_TIMER (10) +#define UX_HOST_CLASS_STORAGE_THREAD_PRIORITY_CLASS 20 +#define UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT 10000 +#define UX_HOST_CLASS_STORAGE_CBI_STATUS_TIMEOUT 3000 +#define UX_HOST_CLASS_STORAGE_CLASS 8 +#define UX_HOST_CLASS_STORAGE_SUBCLASS_RBC 1 +#define UX_HOST_CLASS_STORAGE_SUBCLASS_SFF8020 2 +#define UX_HOST_CLASS_STORAGE_SUBCLASS_UFI 4 +#define UX_HOST_CLASS_STORAGE_SUBCLASS_SFF8070 5 +#define UX_HOST_CLASS_STORAGE_SUBCLASS_SCSI 6 + +#define UX_HOST_CLASS_STORAGE_CBW_SIZE 64 + +#define UX_HOST_CLASS_STORAGE_PROTOCOL_CBI 0 +#define UX_HOST_CLASS_STORAGE_PROTOCOL_CB 1 +#define UX_HOST_CLASS_STORAGE_PROTOCOL_BO 0x50 + +#define UX_HOST_CLASS_STORAGE_DATA_OUT 0 +#define UX_HOST_CLASS_STORAGE_DATA_IN 0x80 + +#define UX_HOST_CLASS_STORAGE_CSW_PASSED 0 +#define UX_HOST_CLASS_STORAGE_CSW_FAILED 1 +#define UX_HOST_CLASS_STORAGE_CSW_PHASE_ERROR 2 + +#define UX_HOST_CLASS_STORAGE_CBW_SIGNATURE_MASK 0x43425355 +#define UX_HOST_CLASS_STORAGE_CBW_TAG_MASK 0x55534243 + +#define UX_HOST_CLASS_STORAGE_MEDIA_NAME "usb disk" + +#define UX_HOST_CLASS_STORAGE_MEDIA_REMOVABLE 0x80 +#define UX_HOST_CLASS_STORAGE_MEDIA_UNKNOWN 0 +#define UX_HOST_CLASS_STORAGE_MEDIA_KNOWN 1 + +#define UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK 0 +#define UX_HOST_CLASS_STORAGE_MEDIA_CDROM 5 +#define UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK 7 +#define UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK 0x55 + +#define UX_HOST_CLASS_STORAGE_RESET 0xff +#define UX_HOST_CLASS_STORAGE_GET_MAX_LUN 0xfe + +#define UX_HOST_CLASS_STORAGE_TRANSPORT_ERROR 1 +#define UX_HOST_CLASS_STORAGE_COMMAND_ERROR 2 +#define UX_HOST_CLASS_STORAGE_SENSE_ERROR 3 + +#define UX_HOST_CLASS_STORAGE_SECTOR_SIZE_FAT 512 +#define UX_HOST_CLASS_STORAGE_SECTOR_SIZE_OTHER 2048 + +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY 10 + +#define UX_HOST_CLASS_STORAGE_START_MEDIA 1 +#define UX_HOST_CLASS_STORAGE_STOP_MEDIA 0 + + +#define UX_HOST_CLASS_STORAGE_MEDIA_UNMOUNTED 0 +#define UX_HOST_CLASS_STORAGE_MEDIA_MOUNTED 1 + +/* Define Storage Class SCSI command constants. */ + +#define UX_HOST_CLASS_STORAGE_SCSI_TEST_READY 0x00 +#define UX_HOST_CLASS_STORAGE_SCSI_REQUEST_SENSE 0x03 +#define UX_HOST_CLASS_STORAGE_SCSI_FORMAT 0x04 +#define UX_HOST_CLASS_STORAGE_SCSI_INQUIRY 0x12 +#define UX_HOST_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT 0x1a +#define UX_HOST_CLASS_STORAGE_SCSI_START_STOP 0x1b +#define UX_HOST_CLASS_STORAGE_SCSI_READ_FORMAT_CAPACITY 0x23 +#define UX_HOST_CLASS_STORAGE_SCSI_READ_CAPACITY 0x25 +#define UX_HOST_CLASS_STORAGE_SCSI_READ16 0x28 +#define UX_HOST_CLASS_STORAGE_SCSI_WRITE16 0x2a +#define UX_HOST_CLASS_STORAGE_SCSI_VERIFY 0x2f +#define UX_HOST_CLASS_STORAGE_SCSI_MODE_SELECT 0x55 +#define UX_HOST_CLASS_STORAGE_SCSI_MODE_SENSE 0x5a +#define UX_HOST_CLASS_STORAGE_SCSI_READ32 0xa8 +#define UX_HOST_CLASS_STORAGE_SCSI_WRITE32 0xaa + + +/* Define Storage Class SCSI command block wrapper constants. */ + +#define UX_HOST_CLASS_STORAGE_CBW_SIGNATURE 0 +#define UX_HOST_CLASS_STORAGE_CBW_TAG 4 +#define UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH 8 +#define UX_HOST_CLASS_STORAGE_CBW_FLAGS 12 +#define UX_HOST_CLASS_STORAGE_CBW_LUN 13 +#define UX_HOST_CLASS_STORAGE_CBW_CB_LENGTH 14 +#define UX_HOST_CLASS_STORAGE_CBW_CB 15 + + +/* Define Storage Class SCSI response status wrapper constants. */ + +#define UX_HOST_CLASS_STORAGE_CSW_SIGNATURE 0 +#define UX_HOST_CLASS_STORAGE_CSW_TAG 4 +#define UX_HOST_CLASS_STORAGE_CSW_DATA_RESIDUE 8 +#define UX_HOST_CLASS_STORAGE_CSW_STATUS 12 +#define UX_HOST_CLASS_STORAGE_CSW_LENGTH 13 + + +/* Define Storage Class SCSI inquiry command constants. */ + +#define UX_HOST_CLASS_STORAGE_INQUIRY_OPERATION 0 +#define UX_HOST_CLASS_STORAGE_INQUIRY_LUN 1 +#define UX_HOST_CLASS_STORAGE_INQUIRY_PAGE_CODE 2 +#define UX_HOST_CLASS_STORAGE_INQUIRY_ALLOCATION_LENGTH 4 +#define UX_HOST_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_UFI 12 +#define UX_HOST_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_SBC 06 + + +/* Define Storage Class SCSI inquiry response constants. */ + +#define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_PERIPHERAL_TYPE 0 +#define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_REMOVABLE_MEDIA 1 +#define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_DATA_FORMAT 3 +#define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_ADDITIONAL_LENGTH 4 +#define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_VENDOR_INFORMATION 8 +#define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_PRODUCT_ID 16 +#define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_PRODUCT_REVISION 32 +#define UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH 36 + + +/* Define Storage Class SCSI start/stop command constants. */ + +#define UX_HOST_CLASS_STORAGE_START_STOP_OPERATION 0 +#define UX_HOST_CLASS_STORAGE_START_STOP_LBUFLAGS 1 +#define UX_HOST_CLASS_STORAGE_START_STOP_START_BIT 4 +#define UX_HOST_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_UFI 12 +#define UX_HOST_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_SBC 12 + + +/* Define Storage Class SCSI mode sense command constants. */ + +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_OPERATION 0 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_LUN 1 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_PC_PAGE_CODE 2 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_PARAMETER_LIST_LENGTH 7 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_UFI 12 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_SBC 12 + +/* Define Storage Class SCSI mode sense command constants. */ + +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_MODE_DATA_LENGTH 0 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_MEDIUM_TYPE_CODE 2 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_ATTRIBUTES_SHORT 2 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_ATTRIBUTES 3 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_ATTRIBUTES_WP 0x80 + +/* Define Storage Class SCSI request sense command constants. */ + +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_OPERATION 0 +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_LUN 1 +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_ALLOCATION_LENGTH 4 +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_COMMAND_LENGTH_UFI 12 +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_COMMAND_LENGTH_SBC 12 + + +/* Define Storage Class request sense response constants. */ + +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ERROR_CODE 0 +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_SENSE_KEY 2 +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_INFORMATION 3 +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_ADD_LENGTH 7 +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE 12 +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE_QUALIFIER 13 +#define UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH 18 + + +/* Define Storage Class read format command constants. */ + +#define UX_HOST_CLASS_STORAGE_READ_FORMAT_OPERATION 0 +#define UX_HOST_CLASS_STORAGE_READ_FORMAT_LUN 1 +#define UX_HOST_CLASS_STORAGE_READ_FORMAT_LBA 2 +#define UX_HOST_CLASS_STORAGE_READ_FORMAT_PARAMETER_LIST_LENGTH 7 +#define UX_HOST_CLASS_STORAGE_READ_FORMAT_COMMAND_LENGTH_UFI 12 +#define UX_HOST_CLASS_STORAGE_READ_FORMAT_COMMAND_LENGTH_SBC 10 +#define UX_HOST_CLASS_STORAGE_READ_FORMAT_RESPONSE_LENGTH 0xFC + +/* Define Storage Class read capacity command constants. */ + +#define UX_HOST_CLASS_STORAGE_READ_CAPACITY_OPERATION 0 +#define UX_HOST_CLASS_STORAGE_READ_CAPACITY_LUN 1 +#define UX_HOST_CLASS_STORAGE_READ_CAPACITY_LBA 2 +#define UX_HOST_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_UFI 12 +#define UX_HOST_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_SBC 10 +#define UX_HOST_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH 8 + +#define UX_HOST_CLASS_STORAGE_READ_CAPACITY_DATA_LBA 0 +#define UX_HOST_CLASS_STORAGE_READ_CAPACITY_DATA_SECTOR_SIZE 4 + + +/* Define Storage Class test unit read command constants. */ + +#define UX_HOST_CLASS_STORAGE_TEST_READY_OPERATION 0 +#define UX_HOST_CLASS_STORAGE_TEST_READY_LUN 1 +#define UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_UFI 12 +#define UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC 6 + +/* Define Storage Class SCSI read command constants. */ + +#define UX_HOST_CLASS_STORAGE_READ_OPERATION 0 +#define UX_HOST_CLASS_STORAGE_READ_LUN 1 +#define UX_HOST_CLASS_STORAGE_READ_LBA 2 +#define UX_HOST_CLASS_STORAGE_READ_TRANSFER_LENGTH 7 +#define UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_UFI 12 +#define UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_SBC 10 + + +/* Define Storage Class SCSI write command constants. */ + +#define UX_HOST_CLASS_STORAGE_WRITE_OPERATION 0 +#define UX_HOST_CLASS_STORAGE_WRITE_LUN 1 +#define UX_HOST_CLASS_STORAGE_WRITE_LBA 2 +#define UX_HOST_CLASS_STORAGE_WRITE_TRANSFER_LENGTH 7 +#define UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_UFI 12 +#define UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC 10 + + +/* Define Storage Class SCSI sense key definition constants. */ + +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_NO_SENSE 0x0 +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_RECOVERED_ERROR 0x1 +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_NOT_READY 0x2 +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_MEDIUM_ERROR 0x3 +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_HARDWARE_ERROR 0x4 +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_ILLEGAL_REQUEST 0x5 +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_UNIT_ATTENTION 0x6 +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_DATA_PROTECT 0x7 +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_BLANK_CHECK 0x8 +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_ABORTED_COMMAND 0x0b +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_VOLUME_OVERFLOW 0x0d +#define UX_HOST_CLASS_STORAGE_SENSE_KEY_MISCOMPARE 0x0e + +/* Define Mode Sense page codes. */ +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_RWER_PAGE 0x01 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_FD_PAGE 0x05 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_RBAC_PAGE 0x1B +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_TP_PAGE 0x1C +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_ALL_PAGE 0x3F + +/* Define Mode Sense page codes response length . */ +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_HEADER_PAGE_LENGTH 0x08 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_RWER_PAGE_LENGTH 0x0c +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_FD_PAGE_LENGTH 0x20 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_RBAC_PAGE_LENGTH 0x0c +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_TP_PAGE_LENGTH 0x08 +#define UX_HOST_CLASS_STORAGE_MODE_SENSE_ALL_PAGE_LENGTH 0xC0 + +/* Define Storage Class useful error sense key/code constant. */ + +#define UX_HOST_CLASS_STORAGE_ERROR_MEDIA_NOT_READ 0x023A00 + + +/* Define Storage Class MS-DOS partition entry constants. */ + +#define UX_HOST_CLASS_STORAGE_PARTITION_SIGNATURE 0xaa55 +#define UX_HOST_CLASS_STORAGE_PARTITION_TABLE_START 446 + +#define UX_HOST_CLASS_STORAGE_PARTITION_BOOT_FLAG 0 +#define UX_HOST_CLASS_STORAGE_PARTITION_START_HEAD 1 +#define UX_HOST_CLASS_STORAGE_PARTITION_START_SECTOR 2 +#define UX_HOST_CLASS_STORAGE_PARTITION_START_TRACK 3 +#define UX_HOST_CLASS_STORAGE_PARTITION_TYPE 4 +#define UX_HOST_CLASS_STORAGE_PARTITION_END_HEAD 5 +#define UX_HOST_CLASS_STORAGE_PARTITION_END_SECTOR 6 +#define UX_HOST_CLASS_STORAGE_PARTITION_END_TRACK 7 +#define UX_HOST_CLASS_STORAGE_PARTITION_SECTORS_BEFORE 8 +#define UX_HOST_CLASS_STORAGE_PARTITION_NUMBER_SECTORS 12 +#define UX_HOST_CLASS_STORAGE_PARTITION_TABLE_SIZE 16 + +#define UX_HOST_CLASS_STORAGE_PARTITION_FAT_12 1 +#define UX_HOST_CLASS_STORAGE_PARTITION_FAT_16 4 +#define UX_HOST_CLASS_STORAGE_PARTITION_EXTENDED 5 +#define UX_HOST_CLASS_STORAGE_PARTITION_FAT_16L 6 +#define UX_HOST_CLASS_STORAGE_PARTITION_FAT_32_1 0x0b +#define UX_HOST_CLASS_STORAGE_PARTITION_FAT_32_2 0x0c +#define UX_HOST_CLASS_STORAGE_PARTITION_FAT_16_LBA_MAPPED 0x0e +#define UX_HOST_CLASS_STORAGE_PARTITION_EXTENDED_LBA_MAPPED 0x0f + +/* Define Storage Class instance structure. */ + +#define UX_HOST_CLASS_STORAGE_CBW_LENGTH 31 +#define UX_HOST_CLASS_STORAGE_CSW_LENGTH 13 +#define UX_HOST_CLASS_STORAGE_CBW_LENGTH_ALIGNED 64 +#define UX_HOST_CLASS_STORAGE_CSW_LENGTH_ALIGNED 64 + + +typedef struct UX_HOST_CLASS_STORAGE_STRUCT +{ + + struct UX_HOST_CLASS_STORAGE_STRUCT + *ux_host_class_storage_next_instance; + UX_HOST_CLASS *ux_host_class_storage_class; + UX_DEVICE *ux_host_class_storage_device; + UX_INTERFACE *ux_host_class_storage_interface; + UX_ENDPOINT *ux_host_class_storage_bulk_out_endpoint; + UX_ENDPOINT *ux_host_class_storage_bulk_in_endpoint; + UX_ENDPOINT *ux_host_class_storage_interrupt_endpoint; + UCHAR ux_host_class_storage_cbw[UX_HOST_CLASS_STORAGE_CBW_LENGTH_ALIGNED]; + UCHAR ux_host_class_storage_saved_cbw[UX_HOST_CLASS_STORAGE_CBW_LENGTH_ALIGNED]; + UCHAR ux_host_class_storage_csw[UX_HOST_CLASS_STORAGE_CSW_LENGTH_ALIGNED]; + UINT ux_host_class_storage_state; + UINT ux_host_class_storage_media_type; + UINT ux_host_class_storage_lun_removable_media_flags[UX_MAX_HOST_LUN]; + UINT ux_host_class_storage_write_protected_media; + UINT ux_host_class_storage_max_lun; + UINT ux_host_class_storage_lun; + UINT ux_host_class_storage_lun_types[UX_MAX_HOST_LUN]; + ULONG ux_host_class_storage_sector_size; + ULONG ux_host_class_storage_data_phase_length; + UINT (*ux_host_class_storage_transport) (struct UX_HOST_CLASS_STORAGE_STRUCT *storage, UCHAR * data_pointer); + ULONG ux_host_class_storage_sense_code; + UCHAR *ux_host_class_storage_memory; + TX_SEMAPHORE ux_host_class_storage_semaphore; +} UX_HOST_CLASS_STORAGE; + + +/* Define Host Storage Class Media structure. */ + +typedef struct UX_HOST_CLASS_STORAGE_MEDIA_STRUCT +{ + + FX_MEDIA ux_host_class_storage_media; + ULONG ux_host_class_storage_media_status; + ULONG ux_host_class_storage_media_lun; + ULONG ux_host_class_storage_media_partition_start; + ULONG ux_host_class_storage_media_sector_size; + VOID *ux_host_class_storage_media_memory; + +} UX_HOST_CLASS_STORAGE_MEDIA; + + +/* Define Storage Class function prototypes. */ + +UINT _ux_host_class_storage_activate(UX_HOST_CLASS_COMMAND *command); +VOID _ux_host_class_storage_cbw_initialize(UX_HOST_CLASS_STORAGE *storage, UINT direction, + ULONG data_transfer_length, UINT command_length); +UINT _ux_host_class_storage_configure(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_storage_device_initialize(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_device_reset(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_device_support_check(UX_HOST_CLASS_STORAGE *storage); +VOID _ux_host_class_storage_driver_entry(FX_MEDIA *media); +UINT _ux_host_class_storage_endpoints_get(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_storage_max_lun_get(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_media_capacity_get(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_media_characteristics_get(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_media_format_capacity_get(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_media_mount(UX_HOST_CLASS_STORAGE *storage, ULONG sector); +UINT _ux_host_class_storage_media_open(UX_HOST_CLASS_STORAGE *storage, ULONG hidden_sectors); +UINT _ux_host_class_storage_media_protection_check(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_media_read(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start, + ULONG sector_count, UCHAR *data_pointer); +UINT _ux_host_class_storage_media_recovery_sense_get(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_media_write(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start, + ULONG sector_count, UCHAR *data_pointer); +UINT _ux_host_class_storage_partition_read(UX_HOST_CLASS_STORAGE *storage, UCHAR *sector_memory, ULONG sector); +UINT _ux_host_class_storage_request_sense(UX_HOST_CLASS_STORAGE *storage); +UINT _ux_host_class_storage_sense_code_translate(UX_HOST_CLASS_STORAGE *storage, UINT status); +UINT _ux_host_class_storage_start_stop(UX_HOST_CLASS_STORAGE *storage, + ULONG start_stop_signal); +VOID _ux_host_class_storage_thread_entry(ULONG class_address); +UINT _ux_host_class_storage_transport(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer); +UINT _ux_host_class_storage_transport_bo(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer); +UINT _ux_host_class_storage_transport_cb(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer); +UINT _ux_host_class_storage_transport_cbi(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer); +UINT _ux_host_class_storage_unit_ready_test(UX_HOST_CLASS_STORAGE *storage); + +/* Define Storage Class API prototypes. */ + +#define ux_host_class_storage_entry _ux_host_class_storage_entry +#define ux_host_class_storage_media_read _ux_host_class_storage_media_read +#define ux_host_class_storage_media_write _ux_host_class_storage_media_write + +#endif diff --git a/common/usbx_host_classes/inc/ux_host_class_swar.h b/common/usbx_host_classes/inc/ux_host_class_swar.h new file mode 100644 index 0000000..2eecbd2 --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_swar.h @@ -0,0 +1,144 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_swar.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX Sierra Wireless AR Class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_SWAR_H +#define UX_HOST_CLASS_SWAR_H + + +/* Define Sierra Wireless AR Class constants. */ + +#define UX_HOST_CLASS_SWAR_CLASS_TRANSFER_TIMEOUT 300000 +#ifndef UX_HOST_CLASS_SWAR_VENDOR_ID +#define UX_HOST_CLASS_SWAR_VENDOR_ID 0X1199 +#define UX_HOST_CLASS_SWAR_PRODUCT_ID 0X68A3 +#endif + +/* Define Sierra Wireless AR Class packet equivalences. */ +#define UX_HOST_CLASS_SWAR_PACKET_SIZE 128 + +/* Define Sierra Wireless AR Class data interface. */ +#define UX_HOST_CLASS_SWAR_DATA_INTERFACE 3 + +/* Define Sierra Wireless AR IOCTL functions. */ +#define UX_HOST_CLASS_SWAR_IOCTL_ABORT_IN_PIPE 1 +#define UX_HOST_CLASS_SWAR_IOCTL_ABORT_OUT_PIPE 2 + +/* Define CDC ACM Reception States. */ + +#define UX_HOST_CLASS_SWAR_RECEPTION_STATE_STOPPED 0 +#define UX_HOST_CLASS_SWAR_RECEPTION_STATE_STARTED 1 +#define UX_HOST_CLASS_SWAR_RECEPTION_STATE_IN_TRANSFER 2 + + +/* Define Sierra Wireless Airprime Class instance structure. */ + +typedef struct UX_HOST_CLASS_SWAR_STRUCT +{ + + struct UX_HOST_CLASS_SWAR_STRUCT + *ux_host_class_swar_next_instance; + UX_HOST_CLASS *ux_host_class_swar_class; + UX_DEVICE *ux_host_class_swar_device; + UX_INTERFACE *ux_host_class_swar_interface; + UX_ENDPOINT *ux_host_class_swar_bulk_out_endpoint; + UX_ENDPOINT *ux_host_class_swar_bulk_in_endpoint; + UINT ux_host_class_swar_state; + TX_SEMAPHORE ux_host_class_swar_semaphore; + + struct UX_HOST_CLASS_SWAR_RECEPTION_STRUCT + *ux_host_class_swar_reception; + ULONG ux_host_class_swar_notification_count; +} UX_HOST_CLASS_SWAR; + +/* Define Sierra Wireless reception structure. */ + +typedef struct UX_HOST_CLASS_SWAR_RECEPTION_STRUCT +{ + + ULONG ux_host_class_swar_reception_state; + ULONG ux_host_class_swar_reception_block_size; + UCHAR *ux_host_class_swar_reception_data_buffer; + ULONG ux_host_class_swar_reception_data_buffer_size; + UCHAR *ux_host_class_swar_reception_data_head; + UCHAR *ux_host_class_swar_reception_data_tail; + VOID (*ux_host_class_swar_reception_callback)(struct UX_HOST_CLASS_SWAR_STRUCT *swar, + UINT status, + UCHAR *reception_buffer, + ULONG reception_size); + +} UX_HOST_CLASS_SWAR_RECEPTION; + +/* Define Sierra Wireless Airprime Classfunction prototypes. */ + +UINT _ux_host_class_swar_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_swar_configure(UX_HOST_CLASS_SWAR *swar); +UINT _ux_host_class_swar_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_swar_endpoints_get(UX_HOST_CLASS_SWAR *swar); +UINT _ux_host_class_swar_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_swar_read (UX_HOST_CLASS_SWAR *swar, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_swar_write(UX_HOST_CLASS_SWAR *swar, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_swar_ioctl(UX_HOST_CLASS_SWAR *swar, ULONG ioctl_function, + VOID *parameter); +VOID _ux_host_class_swar_reception_callback (UX_TRANSFER *transfer_request); +UINT _ux_host_class_swar_reception_stop (UX_HOST_CLASS_SWAR *swar, + UX_HOST_CLASS_SWAR_RECEPTION *swar_reception); +UINT _ux_host_class_swar_reception_start (UX_HOST_CLASS_SWAR *swar, + UX_HOST_CLASS_SWAR_RECEPTION *swar_reception); + +/* Define SWAR Class API prototypes. */ + +#define ux_host_class_swar_entry _ux_host_class_swar_entry +#define ux_host_class_swar_read _ux_host_class_swar_read +#define ux_host_class_swar_write _ux_host_class_swar_write +#define ux_host_class_swar_ioctl _ux_host_class_swar_ioctl +#define ux_host_class_swar_command _ux_host_class_swar_command +#define ux_host_class_swar_reception_stop _ux_host_class_swar_reception_stop +#define ux_host_class_swar_reception_start _ux_host_class_swar_reception_start +#define ux_host_class_swar_setup _ux_host_class_swar_setup + +#endif diff --git a/common/usbx_host_classes/inc/ux_host_class_video.h b/common/usbx_host_classes/inc/ux_host_class_video.h new file mode 100644 index 0000000..7308c87 --- /dev/null +++ b/common/usbx_host_classes/inc/ux_host_class_video.h @@ -0,0 +1,635 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_host_class_video.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX video class. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HOST_CLASS_VIDEO_H +#define UX_HOST_CLASS_VIDEO_H + +/* Define external static data. */ +extern UCHAR _ux_system_class_video_interface_descriptor_structure[]; +extern UCHAR _ux_system_class_video_input_terminal_descriptor_structure[]; +extern UCHAR _ux_system_class_video_input_header_descriptor_structure[]; +extern UCHAR _ux_system_class_video_processing_unit_descriptor_structure[]; +extern UCHAR _ux_system_class_video_streaming_interface_descriptor_structure[]; +extern UCHAR _ux_system_class_video_streaming_endpoint_descriptor_structure[]; +extern UCHAR _ux_system_class_video_frame_descriptor_structure[]; + +extern UCHAR _ux_system_host_class_video_name[]; + +/* Define Video Class IOCTL constants. */ + +#define UX_HOST_CLASS_VIDEO_IOCTL_GET_INPUT_TERMINAL 0x01 +#define UX_HOST_CLASS_VIDEO_IOCTL_GET_FORMAT_NUMBER 0x02 +#define UX_HOST_CLASS_VIDEO_IOCTL_GET_FORMAT_DATA 0x03 +#define UX_HOST_CLASS_VIDEO_IOCTL_GET_FRAME_NUMBER 0x04 +#define UX_HOST_CLASS_VIDEO_IOCTL_GET_FRAME_DATA 0x05 +#define UX_HOST_CLASS_VIDEO_IOCTL_CHANNEL_START 0x06 +#define UX_HOST_CLASS_VIDEO_IOCTL_CHANNEL_STOP 0x07 +#define UX_HOST_CLASS_VIDEO_IOCTL_GET_FRAME_INTERVAL 0x08 + +#define UX_HOST_CLASS_VIDEO_IOCTL_ABORT_IN_PIPE 0x80 + +/* Define Video Class main constants. */ + +#define UX_HOST_CLASS_VIDEO_CLASS_TRANSFER_TIMEOUT 30 +#define UX_HOST_CLASS_VIDEO_CLASS 0x0e +#define UX_HOST_CLASS_VIDEO_SUBCLASS_UNDEFINED 0 +#define UX_HOST_CLASS_VIDEO_SUBCLASS_CONTROL 1 +#define UX_HOST_CLASS_VIDEO_SUBCLASS_STREAMING 2 + + +/* Define Video Class main descriptor types. */ + +#define UX_HOST_CLASS_VIDEO_CS_UNDEFINED 0x20 +#define UX_HOST_CLASS_VIDEO_CS_DEVICE 0x21 +#define UX_HOST_CLASS_VIDEO_CS_CONFIGURATION 0x22 +#define UX_HOST_CLASS_VIDEO_CS_STRING 0x23 +#define UX_HOST_CLASS_VIDEO_CS_INTERFACE 0x24 +#define UX_HOST_CLASS_VIDEO_CS_ENDPOINT 0x25 + +/* Define Video Class specific VC . */ + +#define UX_HOST_CLASS_VIDEO_VC_DESCRIPTOR_UNDEFINED 0x00 +#define UX_HOST_CLASS_VIDEO_VC_HEADER 0x01 +#define UX_HOST_CLASS_VIDEO_VC_INPUT_TERMINAL 0x02 +#define UX_HOST_CLASS_VIDEO_VC_OUTPUT_TERMINAL 0x03 +#define UX_HOST_CLASS_VIDEO_VC_SELECTOR_UNIT 0x04 +#define UX_HOST_CLASS_VIDEO_VC_PROCESSING_UNIT 0x05 +#define UX_HOST_CLASS_VIDEO_VC_EXTENSION_UNIT 0x06 + +/* Define Video Class specific VS . */ + +#define UX_HOST_CLASS_VIDEO_VS_UNDEFINED 0x00 +#define UX_HOST_CLASS_VIDEO_VS_INPUT_HEADER 0x01 +#define UX_HOST_CLASS_VIDEO_VS_OUTPUT_HEADER 0x02 +#define UX_HOST_CLASS_VIDEO_VS_STILL_IMAGE_FRAME 0x03 +#define UX_HOST_CLASS_VIDEO_VS_FORMAT_UNCOMPRESSED 0x04 +#define UX_HOST_CLASS_VIDEO_VS_FRAME_UNCOMPRESSED 0x05 +#define UX_HOST_CLASS_VIDEO_VS_FORMAT_MJPEG 0x06 +#define UX_HOST_CLASS_VIDEO_VS_FRAME_MJPEG 0x07 +#define UX_HOST_CLASS_VIDEO_VS_FORMAT_MPEG2TS 0x0A +#define UX_HOST_CLASS_VIDEO_VS_FORMAT_DV 0x0C +#define UX_HOST_CLASS_VIDEO_VS_COLORFORMAT 0x0D +#define UX_HOST_CLASS_VIDEO_VS_FORMAT_FRAME_BASED 0x10 +#define UX_HOST_CLASS_VIDEO_VS_FRAME_FRAME_BASED 0x11 +#define UX_HOST_CLASS_VIDEO_VS_FORMAT_STREAM_BASED 0x12 + + +/* Define Video Class specific Control Selectors. */ + +#define UX_HOST_CLASS_VIDEO_CT_CONTROL_UNDEFINED 0x00 +#define UX_HOST_CLASS_VIDEO_CT_SCANNING_MODE_CONTROL 0x01 +#define UX_HOST_CLASS_VIDEO_CT_AE_MODE_CONTROL 0x02 +#define UX_HOST_CLASS_VIDEO_CT_AE_PRIORITY_CONTROL 0x03 +#define UX_HOST_CLASS_VIDEO_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 +#define UX_HOST_CLASS_VIDEO_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 +#define UX_HOST_CLASS_VIDEO_CT_FOCUS_ABSOLUTE_CONTROL 0x06 +#define UX_HOST_CLASS_VIDEO_CT_FOCUS_RELATIVE_CONTROL 0x07 +#define UX_HOST_CLASS_VIDEO_CT_FOCUS_AUTO_CONTROL 0x08 +#define UX_HOST_CLASS_VIDEO_CT_IRIS_ABSOLUTE_CONTROL 0x09 +#define UX_HOST_CLASS_VIDEO_CT_IRIS_RELATIVE_CONTROL 0x0A +#define UX_HOST_CLASS_VIDEO_CT_ZOOM_ABSOLUTE_CONTROL 0x0B +#define UX_HOST_CLASS_VIDEO_CT_ZOOM_RELATIVE_CONTROL 0x0C +#define UX_HOST_CLASS_VIDEO_CT_PANTILT_ABSOLUTE_CONTROL 0x0D +#define UX_HOST_CLASS_VIDEO_CT_PANTILT_RELATIVE_CONTROL 0x0E +#define UX_HOST_CLASS_VIDEO_CT_ROLL_ABSOLUTE_CONTROL 0x0F +#define UX_HOST_CLASS_VIDEO_CT_ROLL_RELATIVE_CONTROL 0x10 +#define UX_HOST_CLASS_VIDEO_CT_PRIVACY_CONTROL 0x11 + +#define UX_HOST_CLASS_VIDEO_PU_CONTROL_UNDEFINED 0x00 +#define UX_HOST_CLASS_VIDEO_PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 +#define UX_HOST_CLASS_VIDEO_PU_BRIGHTNESS_CONTROL 0x02 +#define UX_HOST_CLASS_VIDEO_PU_CONTRAST_CONTROL 0x03 +#define UX_HOST_CLASS_VIDEO_PU_GAIN_CONTROL 0x04 +#define UX_HOST_CLASS_VIDEO_PU_POWER_LINE_FREQUENCY_CONTROL 0x05 +#define UX_HOST_CLASS_VIDEO_PU_HUE_CONTROL 0x06 +#define UX_HOST_CLASS_VIDEO_PU_SATURATION_CONTROL 0x07 +#define UX_HOST_CLASS_VIDEO_PU_SHARPNESS_CONTROL 0x08 +#define UX_HOST_CLASS_VIDEO_PU_GAMMA_CONTROL 0x09 +#define UX_HOST_CLASS_VIDEO_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0A +#define UX_HOST_CLASS_VIDEO_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0B +#define UX_HOST_CLASS_VIDEO_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0C +#define UX_HOST_CLASS_VIDEO_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0D +#define UX_HOST_CLASS_VIDEO_PU_DIGITAL_MULTIPLIER_CONTROL 0x0E +#define UX_HOST_CLASS_VIDEO_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0F +#define UX_HOST_CLASS_VIDEO_PU_HUE_AUTO_CONTROL 0x10 +#define UX_HOST_CLASS_VIDEO_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 +#define UX_HOST_CLASS_VIDEO_PU_ANALOG_LOCK_STATUS_CONTROL 0x12 + + +#define UX_HOST_CLASS_VIDEO_VS_CONTROL_UNDEFINED 0x00 +#define UX_HOST_CLASS_VIDEO_VS_PROBE_CONTROL 0x01 +#define UX_HOST_CLASS_VIDEO_VS_COMMIT_CONTROL 0x02 +#define UX_HOST_CLASS_VIDEO_VS_STILL_PROBE_CONTROL 0x03 +#define UX_HOST_CLASS_VIDEO_VS_STILL_COMMIT_CONTROL 0x04 +#define UX_HOST_CLASS_VIDEO_VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 +#define UX_HOST_CLASS_VIDEO_VS_STREAM_ERROR_CODE_CONTROL 0x06 +#define UX_HOST_CLASS_VIDEO_VS_GENERATE_KEY_FRAME_CONTROL 0x07 +#define UX_HOST_CLASS_VIDEO_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 +#define UX_HOST_CLASS_VIDEO_VS_SYNCH_DELAY_CONTROL 0x09 + + +/* Define USB Video Class terminal types. */ + +#define UX_HOST_CLASS_VIDEO_TT_VENDOR_SPECIFIC 0x0100 +#define UX_HOST_CLASS_VIDEO_TT_STREAMING 0x0101 + +#define UX_HOST_CLASS_VIDEO_ITT_VENDOR_SPECIFIC 0x0200 +#define UX_HOST_CLASS_VIDEO_ITT_CAMERA 0x0201 +#define UX_HOST_CLASS_VIDEO_ITT_MEDIA_TRANSPORT_INPUT 0x0202 + +#define UX_HOST_CLASS_VIDEO_OTT_VENDOR_SPECIFIC 0x0300 +#define UX_HOST_CLASS_VIDEO_OTT_CAMERA 0x0301 +#define UX_HOST_CLASS_VIDEO_OTT_MEDIA_TRANSPORT_INPUT 0x0302 + + +/* Define USB Video Class Request Error Code Control. */ + +#define UX_HOST_CLASS_VIDEO_REQUEST_ERROR_CODE_NO_ERROR 0x00 +#define UX_HOST_CLASS_VIDEO_REQUEST_ERROR_CODE_NOT_READY 0x01 +#define UX_HOST_CLASS_VIDEO_REQUEST_ERROR_CODE_WRONG_STATE 0x02 +#define UX_HOST_CLASS_VIDEO_REQUEST_ERROR_CODE_POWER 0x03 +#define UX_HOST_CLASS_VIDEO_REQUEST_ERROR_CODE_OUT_OF_RANGE 0x04 +#define UX_HOST_CLASS_VIDEO_REQUEST_ERROR_CODE_INVALID_INPUT 0x05 +#define UX_HOST_CLASS_VIDEO_REQUEST_ERROR_CODE_INVALID_CONTROL 0x06 +#define UX_HOST_CLASS_VIDEO_REQUEST_ERROR_CODE_INVALID_REQUEST 0x07 +#define UX_HOST_CLASS_VIDEO_REQUEST_ERROR_CODE_UNKNOWN 0xFF + + +/* Define Video Class encoding format types. */ + +#define UX_HOST_CLASS_VIDEO_INTERFACE_DESCRIPTOR_ENTRIES 8 +#define UX_HOST_CLASS_VIDEO_INTERFACE_DESCRIPTOR_LENGTH 8 + +#define UX_HOST_CLASS_VIDEO_INPUT_TERMINAL_DESCRIPTOR_ENTRIES 7 +#define UX_HOST_CLASS_VIDEO_INPUT_TERMINAL_DESCRIPTOR_LENGTH 8 + +#define UX_HOST_CLASS_VIDEO_INPUT_HEADER_DESCRIPTOR_ENTRIES 12 +#define UX_HOST_CLASS_VIDEO_INPUT_HEADER_DESCRIPTOR_LENGTH 13 + +#define UX_HOST_CLASS_VIDEO_PROCESSING_UNIT_DESCRIPTOR_ENTRIES 8 +#define UX_HOST_CLASS_VIDEO_PROCESSING_UNIT_DESCRIPTOR_LENGTH 9 + +#define UX_HOST_CLASS_VIDEO_STREAMING_INTERFACE_DESCRIPTOR_ENTRIES 6 +#define UX_HOST_CLASS_VIDEO_STREAMING_INTERFACE_DESCRIPTOR_LENGTH 6 + +#define UX_HOST_CLASS_VIDEO_STREAMING_ENDPOINT_DESCRIPTOR_ENTRIES 6 +#define UX_HOST_CLASS_VIDEO_STREAMING_ENDPOINT_DESCRIPTOR_LENGTH 6 + +#define UX_HOST_CLASS_VIDEO_FRAME_DESCRIPTOR_ENTRIES 12 +#define UX_HOST_CLASS_VIDEO_FRAME_DESCRIPTOR_LENGTH 30 + + +/* Define Video Class specific interface descriptor. */ + +#define UX_HOST_CLASS_VIDEO_MAX_CHANNEL 8 +#define UX_HOST_CLASS_VIDEO_NAME_LENGTH 64 + +/* Define Video Class specific request codes. */ + +#define UX_HOST_CLASS_VIDEO_REQUEST_CODE_UNDEFINED 0x00 +#define UX_HOST_CLASS_VIDEO_SET_CUR 0x01 +#define UX_HOST_CLASS_VIDEO_GET_CUR 0x81 +#define UX_HOST_CLASS_VIDEO_GET_MIN 0x82 +#define UX_HOST_CLASS_VIDEO_GET_MAX 0x83 +#define UX_HOST_CLASS_VIDEO_GET_RES 0x84 +#define UX_HOST_CLASS_VIDEO_GET_INFO 0x86 +#define UX_HOST_CLASS_VIDEO_GET_DEF 0x87 + +/* Define Video Class error codes. */ + +#define UX_HOST_CLASS_VIDEO_WRONG_TYPE 0x90 +#define UX_HOST_CLASS_VIDEO_WRONG_INTERFACE 0x91 +#define UX_HOST_CLASS_VIDEO_PARAMETER_ERROR 0x92 + +/* Define Video Class Terminal Control Selectors. */ +#define UX_HOST_CLASS_VIDEO_TCS_VC_CONTROL_UNDEFINED 0x00 +#define UX_HOST_CLASS_VIDEO_TCS_VC_VIDEO_POWER_MODE_CONTROL 0x01 +#define UX_HOST_CLASS_VIDEO_TCS_VC_REQUEST_ERROR_CODE_CONTROL 0x02 + +#define UX_HOST_CLASS_VIDEO_TCS_TE_CONTROL_UNDEFINED 0x00 + +#define UX_HOST_CLASS_VIDEO_TCS_SU_CONTROL_UNDEFINED 0x00 +#define UX_HOST_CLASS_VIDEO_TCS_SU_INPUT_SELECT_CONTROL 0x01 + +#define UX_HOST_CLASS_VIDEO_TCS_CT_CONTROL_UNDEFINED 0x00 +#define UX_HOST_CLASS_VIDEO_TCS_CT_SCANNING_MODE_CONTROL 0x01 +#define UX_HOST_CLASS_VIDEO_TCS_CT_AE_MODE_CONTROL 0x02 +#define UX_HOST_CLASS_VIDEO_TCS_CT_AE_PRIORITY_CONTROL 0x03 +#define UX_HOST_CLASS_VIDEO_TCS_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 +#define UX_HOST_CLASS_VIDEO_TCS_CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 +#define UX_HOST_CLASS_VIDEO_TCS_CT_FOCUS_ABSOLUTE_CONTROL 0x06 +#define UX_HOST_CLASS_VIDEO_TCS_CT_FOCUS_RELATIVE_CONTROL 0x07 +#define UX_HOST_CLASS_VIDEO_TCS_CT_FOCUS_AUTO_CONTROL 0x08 +#define UX_HOST_CLASS_VIDEO_TCS_CT_IRIS_ABSOLUTE_CONTROL 0x09 +#define UX_HOST_CLASS_VIDEO_TCS_CT_IRIS_RELATIVE_CONTROL 0x0A +#define UX_HOST_CLASS_VIDEO_TCS_CT_ZOOM_ABSOLUTE_CONTROL 0x0B +#define UX_HOST_CLASS_VIDEO_TCS_CT_ZOOM_RELATIVE_CONTROL 0x0C +#define UX_HOST_CLASS_VIDEO_TCS_CT_PANTILT_ABSOLUTE_CONTROL 0x0D +#define UX_HOST_CLASS_VIDEO_TCS_CT_PANTILT_RELATIVE_CONTROL 0x0E +#define UX_HOST_CLASS_VIDEO_TCS_CT_ROLL_ABSOLUTE_CONTROL 0x0F +#define UX_HOST_CLASS_VIDEO_TCS_CT_ROLL_RELATIVE_CONTROL 0x10 +#define UX_HOST_CLASS_VIDEO_TCS_CT_PRIVACY_CONTROL 0x11 + +#define UX_HOST_CLASS_VIDEO_TCS_PU_CONTROL_UNDEFINED 0x00 +#define UX_HOST_CLASS_VIDEO_TCS_PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 +#define UX_HOST_CLASS_VIDEO_TCS_PU_BRIGHTNESS_CONTROL 0x02 +#define UX_HOST_CLASS_VIDEO_TCS_PU_CONTRAST_CONTROL 0x03 +#define UX_HOST_CLASS_VIDEO_TCS_PU_GAIN_CONTROL 0x04 +#define UX_HOST_CLASS_VIDEO_TCS_PU_POWER_LINE_FREQUENCY_CONTROL 0x05 +#define UX_HOST_CLASS_VIDEO_TCS_PU_HUE_CONTROL 0x06 +#define UX_HOST_CLASS_VIDEO_TCS_PU_SATURATION_CONTROL 0x07 +#define UX_HOST_CLASS_VIDEO_TCS_PU_SHARPNESS_CONTROL 0x08 +#define UX_HOST_CLASS_VIDEO_TCS_PU_GAMMA_CONTROL 0x09 +#define UX_HOST_CLASS_VIDEO_TCS_PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0A +#define UX_HOST_CLASS_VIDEO_TCS_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0B +#define UX_HOST_CLASS_VIDEO_TCS_PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0C + +#define UX_HOST_CLASS_VIDEO_TCS_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0D +#define UX_HOST_CLASS_VIDEO_TCS_PU_DIGITAL_MULTIPLIER_CONTROL 0x0E +#define UX_HOST_CLASS_VIDEO_TCS_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0F +#define UX_HOST_CLASS_VIDEO_TCS_PU_HUE_AUTO_CONTROL 0x10 +#define UX_HOST_CLASS_VIDEO_TCS_PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 +#define UX_HOST_CLASS_VIDEO_TCS_PU_ANALOG_LOCK_STATUS_CONTROL 0x12 + +#define UX_HOST_CLASS_VIDEO_TCS_XU_CONTROL_UNDEFINED 0x00 + +#define UX_HOST_CLASS_VIDEO_TCS_VS_CONTROL_UNDEFINED 0x00 +#define UX_HOST_CLASS_VIDEO_TCS_VS_PROBE_CONTROL 0x01 +#define UX_HOST_CLASS_VIDEO_TCS_VS_COMMIT_CONTROL 0x02 +#define UX_HOST_CLASS_VIDEO_TCS_VS_STILL_PROBE_CONTROL 0x03 +#define UX_HOST_CLASS_VIDEO_TCS_VS_STILL_COMMIT_CONTROL 0x04 +#define UX_HOST_CLASS_VIDEO_TCS_VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 +#define UX_HOST_CLASS_VIDEO_TCS_VS_STREAM_ERROR_CODE_CONTROL 0x06 +#define UX_HOST_CLASS_VIDEO_TCS_VS_GENERATE_KEY_FRAME_CONTROL 0x07 +#define UX_HOST_CLASS_VIDEO_TCS_VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 +#define UX_HOST_CLASS_VIDEO_TCS_VS_SYNCH_DELAY_CONTROL 0x09 + +/* Define Video Class Probe and Commit Controls */ + +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_LENGTH 34 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_HINT 0 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_FORMAT_INDEX 2 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_FRAME_INDEX 3 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_FRAME_INTERVAL 4 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_KEY_FRAME_RATE 8 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_PFRAME_RAE 10 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_COMP_QUALITY 12 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_COMP_WINDOW_SIZE 14 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_DELAY 16 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_MAX_VIDEO_FRAME_SIZE 18 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_MAX_PAYLOAD_TRANSFER_SIZE 22 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_CLOCK_FREQUENCY 26 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_FRAMING_INFO 30 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_PREFERED_VERSION 31 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_MIN_VERSION 32 +#define UX_HOST_CLASS_VIDEO_PROBE_COMMIT_MAX_VERSION 33 + +#ifndef UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_COUNT +#define UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_COUNT 8 +#endif + +typedef struct UX_HOST_CLASS_VIDEO_INTERFACE_HEADER_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bcdUVC; + ULONG wTotalLength; + ULONG dwClockFrequency; + ULONG bInCollection; + ULONG baInterfaceNr; +} UX_HOST_CLASS_VIDEO_INTERFACE_HEADER_DESCRIPTOR; + +/* Define Video Class specific input header interface descriptor. */ + +typedef struct UX_HOST_CLASS_VIDEO_INPUT_TERMINAL_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bTerminalID; + ULONG wTerminalType; + ULONG bAssocTerminal; + ULONG iTerminal; +} UX_HOST_CLASS_VIDEO_INPUT_TERMINAL_DESCRIPTOR; + +/* Define Video Class specific input header interface descriptor. */ + +typedef struct UX_HOST_CLASS_VIDEO_INPUT_HEADER_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubType; + ULONG bNumFormats; + ULONG wTotalLength; + ULONG bEndpointAddress; + ULONG bmInfo; + ULONG bTerminalLink; + ULONG bStillCaptureMethod; + ULONG bTriggerSupport; + ULONG bTriggerUsage; + ULONG bControlSize; + ULONG bmaControls; +} UX_HOST_CLASS_VIDEO_INPUT_HEADER_DESCRIPTOR; + +/* Define Video Class Selector descriptor. */ + +typedef struct UX_HOST_CLASS_VIDEO_SELECTOR_UNIT_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bUnitID; + ULONG bNrInPins; + ULONG baSourceID; +} UX_HOST_CLASS_VIDEO_SELECTOR_UNIT_DESCRIPTOR; + +/* Define Video Class Camera Terminal descriptor. */ + +typedef struct UX_HOST_CLASS_VIDEO_CAMERA_TERMINAL_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bTerminalID; + ULONG wTerminalType; + ULONG bAssocTerminal; + ULONG iTerminal; + ULONG wObjectiveFocalLengthMin; + ULONG wObjectiveFocalLengthMax; + ULONG wOcularFocalLength; + ULONG bControlSize; + ULONG bmControls; +} UX_HOST_CLASS_VIDEO_CAMERA_TERMINAL_DESCRIPTOR; + +/* Define Video Class Frame descriptor. */ + +typedef struct UX_HOST_CLASS_VIDEO_FRAME_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bFrameIndex; + ULONG bmCapabilities; + ULONG wWidth; + ULONG wHeight; + ULONG dwMinBitRate; + ULONG dwMaxBitRate; + ULONG dwMaxVideoFrameBufferSize; + ULONG dwDefaultFrameInterval; + ULONG bFrameIntervalType; +} UX_HOST_CLASS_VIDEO_FRAME_DESCRIPTOR; + + + +/* Define Video Class Processing Unit descriptor. */ + +typedef struct UX_HOST_CLASS_VIDEO_PROCESSING_UNIT_DESCRIPTOR_STRUCT +{ + + ULONG bLength; + ULONG bDescriptorType; + ULONG bDescriptorSubtype; + ULONG bUnitID; + ULONG bSourceID; + ULONG wMaxMultiplier; + ULONG bControlSize; + ULONG bmControls; + ULONG iProcessing; + ULONG bmVideoStandards; +} UX_HOST_CLASS_VIDEO_PROCESSING_UNIT_DESCRIPTOR; + + +/* Define Video Class instance structure. */ + +typedef struct UX_HOST_CLASS_VIDEO_STRUCT +{ + + struct UX_HOST_CLASS_VIDEO_STRUCT + *ux_host_class_video_next_instance; + UX_HOST_CLASS *ux_host_class_video_class; + UX_DEVICE *ux_host_class_video_device; + UX_INTERFACE *ux_host_class_video_streaming_interface; + ULONG ux_host_class_video_control_interface_number; + UX_ENDPOINT *ux_host_class_video_isochronous_endpoint; + UINT ux_host_class_video_state; + ULONG ux_host_class_video_feature_unit_id; + ULONG ux_host_class_video_terminal_id; + ULONG ux_host_class_video_terminal_type; + UCHAR *ux_host_class_video_configuration_descriptor; + ULONG ux_host_class_video_configuration_descriptor_length; + UCHAR ux_host_class_video_name[UX_HOST_CLASS_VIDEO_NAME_LENGTH]; + ULONG ux_host_class_video_number_formats; + ULONG ux_host_class_video_length_formats; + UCHAR *ux_host_class_video_format_address; + UCHAR *ux_host_class_video_current_format_address; + ULONG ux_host_class_video_current_format; + ULONG ux_host_class_video_number_frames; + ULONG ux_host_class_video_current_frame; + UCHAR *ux_host_class_video_current_frame_address; + ULONG ux_host_class_video_current_frame_interval; + ULONG ux_host_class_video_current_max_payload_size; + UX_TRANSFER ux_host_class_video_transfer_requests[UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_COUNT]; + ULONG ux_host_class_video_transfer_request_start_index; + ULONG ux_host_class_video_transfer_request_end_index; + TX_SEMAPHORE ux_host_class_video_semaphore; + VOID (*ux_host_class_video_transfer_completion_function)(UX_TRANSFER*); + +} UX_HOST_CLASS_VIDEO; + + +/* Define Video Class isochronous USB transfer request structure. */ + +typedef struct UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_STRUCT +{ + + ULONG ux_host_class_video_transfer_request_status; + UCHAR * ux_host_class_video_transfer_request_data_pointer; + ULONG ux_host_class_video_transfer_request_requested_length; + ULONG ux_host_class_video_transfer_request_actual_length; + VOID (*ux_host_class_video_transfer_request_completion_function) (struct UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_STRUCT *); + TX_SEMAPHORE ux_host_class_video_transfer_request_semaphore; + VOID *ux_host_class_video_transfer_request_class_instance; + UINT ux_host_class_video_transfer_request_completion_code; + struct UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_STRUCT + *ux_host_class_video_transfer_request_next_video_transfer_request; + UX_TRANSFER ux_host_class_video_transfer_request; +} UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST; + + +/* Define Video Class channel/value control structures. */ + +typedef struct UX_HOST_CLASS_VIDEO_CONTROL_STRUCT +{ + + ULONG ux_host_class_video_control; + LONG ux_host_class_video_control_min; + LONG ux_host_class_video_control_max; + LONG ux_host_class_video_control_res; + LONG ux_host_class_video_control_cur; +} UX_HOST_CLASS_VIDEO_CONTROL; + +/* Define Video Class input terminal structures. */ + +typedef struct UX_HOST_CLASS_VIDEO_PARAMETER_INPUT_TERMINAL_STRUCT +{ + + ULONG ux_host_class_video_parameter_input_terminal_id; + ULONG ux_host_class_video_parameter_input_terminal_type; + +} UX_HOST_CLASS_VIDEO_PARAMETER_INPUT_TERMINAL; + +/* Define Video Class format number structure. */ + +typedef struct UX_HOST_CLASS_VIDEO_PARAMETER_NUMBER_FORMATS_STRUCT +{ + + ULONG ux_host_class_video_parameter_number_formats; + +} UX_HOST_CLASS_VIDEO_PARAMETER_NUMBER_FORMATS; + +/* Define Video Class format data structure. */ + +typedef struct UX_HOST_CLASS_VIDEO_PARAMETER_FORMAT_DATA_STRUCT +{ + + ULONG ux_host_class_video_parameter_format_requested; + ULONG ux_host_class_video_parameter_format_subtype; + ULONG ux_host_class_video_parameter_number_frame_descriptors; + +} UX_HOST_CLASS_VIDEO_PARAMETER_FORMAT_DATA; + +typedef struct UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_DATA_STRUCT +{ + + ULONG ux_host_class_video_parameter_frame_requested; + ULONG ux_host_class_video_parameter_frame_subtype; + ULONG ux_host_class_video_parameter_frame_width; + ULONG ux_host_class_video_parameter_frame_height; + ULONG ux_host_class_video_parameter_default_frame_interval; + ULONG ux_host_class_video_parameter_frame_interval_type; + +} UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_DATA; + + +typedef struct UX_HOST_CLASS_VIDEO_PARAMETER_CHANNEL_STRUCT +{ + + ULONG ux_host_class_video_parameter_channel_bandwidth_selection; + ULONG ux_host_class_video_parameter_format_requested; + ULONG ux_host_class_video_parameter_frame_requested; + ULONG ux_host_class_video_parameter_frame_interval_requested; + +} UX_HOST_CLASS_VIDEO_PARAMETER_CHANNEL; + +typedef struct UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_INTERVAL_STRUCT +{ + + ULONG ux_host_class_video_parameter_frame_requested; + ULONG *ux_host_class_video_parameter_frame_interval_buffer; + ULONG ux_host_class_video_parameter_frame_interval_buffer_length; + ULONG ux_host_class_video_parameter_frame_interval_buffer_length_written; + +} UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_INTERVAL; + +/* Define Video Class function prototypes. */ + +UINT _ux_host_class_video_activate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_video_configure(UX_HOST_CLASS_VIDEO *video); +UINT _ux_host_class_video_control_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_CONTROL *video_control); +UINT _ux_host_class_video_control_value_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_CONTROL *video_control); +UINT _ux_host_class_video_control_value_set(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_CONTROL *video_control); +UINT _ux_host_class_video_deactivate(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_video_descriptor_get(UX_HOST_CLASS_VIDEO *video); +UINT _ux_host_class_video_endpoints_get(UX_HOST_CLASS_VIDEO *video); +UINT _ux_host_class_video_entry(UX_HOST_CLASS_COMMAND *command); +UINT _ux_host_class_video_read(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST *video_transfer_request); +UINT _ux_host_class_video_transfer_request(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST *video_transfer_request); +VOID _ux_host_class_video_transfer_request_completed(UX_TRANSFER *transfer_request); +VOID _ux_host_class_video_transfer_request_callback(UX_TRANSFER *transfer_request); +UINT _ux_host_class_video_control_list_get(UX_HOST_CLASS_VIDEO *video); +UINT _ux_host_class_video_input_format_get(UX_HOST_CLASS_VIDEO *video); +UINT _ux_host_class_video_input_terminal_get(UX_HOST_CLASS_VIDEO *video); +UINT _ux_host_class_video_alternate_setting_locate(UX_HOST_CLASS_VIDEO *video, UINT max_payload_size, UINT *alternate_setting); +UINT _ux_host_class_video_ioctl(UX_HOST_CLASS_VIDEO *video, ULONG ioctl_function, VOID *parameter); +UINT _ux_host_class_video_format_data_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_PARAMETER_FORMAT_DATA *format_parameter); +UINT _ux_host_class_video_frame_data_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_DATA *frame_parameter); +UINT _ux_host_class_video_frame_interval_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_INTERVAL *interval_parameter); +UINT _ux_host_class_video_channel_start(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_PARAMETER_CHANNEL *video_parameter); +UINT _ux_host_class_video_stop(UX_HOST_CLASS_VIDEO *video); +UINT _ux_host_class_video_start(UX_HOST_CLASS_VIDEO *video); +UINT _ux_host_class_video_frame_parameters_set(UX_HOST_CLASS_VIDEO *video, ULONG frame_format, ULONG width, ULONG height, ULONG frame_interval); +ULONG _ux_host_class_video_max_payload_get(UX_HOST_CLASS_VIDEO *video); +UINT _ux_host_class_video_transfer_buffer_add(UX_HOST_CLASS_VIDEO *video, UCHAR* buffer); +UINT _ux_host_class_video_transfer_buffers_add(UX_HOST_CLASS_VIDEO *video, UCHAR** buffers, ULONG num_buffers); +VOID _ux_host_class_video_transfer_callback_set(UX_HOST_CLASS_VIDEO *video, VOID (*callback_function)(UX_TRANSFER*)); + + +/* Define Video Class API prototypes. */ + +#define ux_host_class_video_entry _ux_host_class_video_entry +#define ux_host_class_video_control_get _ux_host_class_video_control_get +#define ux_host_class_video_control_value_get _ux_host_class_video_control_value_get +#define ux_host_class_video_control_value_set _ux_host_class_video_control_value_set +#define ux_host_class_video_read _ux_host_class_video_read +#define ux_host_class_video_ioctl _ux_host_class_video_ioctl +#define ux_host_class_video_start _ux_host_class_video_start +#define ux_host_class_video_stop _ux_host_class_video_stop +#define ux_host_class_video_frame_parameters_set _ux_host_class_video_frame_parameters_set +#define ux_host_class_video_max_payload_get _ux_host_class_video_max_payload_get +#define ux_host_class_video_transfer_buffer_add _ux_host_class_video_transfer_buffer_add +#define ux_host_class_video_transfer_buffers_add _ux_host_class_video_transfer_buffers_add +#define ux_host_class_video_transfer_callback_set _ux_host_class_video_transfer_callback_set + +#endif + + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_activate.c b/common/usbx_host_classes/src/ux_host_class_asix_activate.c new file mode 100644 index 0000000..d5b2778 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_activate.c @@ -0,0 +1,281 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Asix Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + +UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates the asix instance, configure the device. */ +/* WARNING !!!! The NX_PHYSICAL_HEADER should be set to 20 in nx_api.h */ +/* */ +/* INPUT */ +/* */ +/* command Asix class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_asix_configure Configure asix class */ +/* _ux_host_class_asix_endpoints_get Get endpoints of asix */ +/* _ux_host_class_asix_setup Set up asix */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_utility_thread_create Create thread */ +/* _ux_utility_thread_delete Delete thread */ +/* nx_packet_pool_create Create NetX packet pool */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_asix_entry Entry of asix class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_asix_activate(UX_HOST_CLASS_COMMAND *command) +{ +#if NX_PHYSICAL_HEADER < 20 + + UX_PARAMETER_NOT_USED(command); + + /* Error trap - function not supported due to NX lib settings. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + return(UX_FUNCTION_NOT_SUPPORTED); +#else +UX_DEVICE *device; +UX_HOST_CLASS_ASIX *asix; +UINT status; +UX_TRANSFER *transfer_request; + + /* We need to make sure that the value of the NX_PHYSICAL_HEADER is at least 20. + This should be changed in the nx_user.h file */ + + + /* The asix class is always activated by the device descriptor. */ + device = (UX_DEVICE *) command -> ux_host_class_command_container; + + /* Obtain memory for this class instance. */ + asix = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, sizeof(UX_HOST_CLASS_ASIX)); + if (asix == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance. */ + asix -> ux_host_class_asix_class = command -> ux_host_class_command_class_ptr; + + /* Store the device container into the asix class instance. */ + asix -> ux_host_class_asix_device = device; + + /* Store the instance in the device container, this is for the USBX stack + when it needs to invoke the class for deactivation. */ + device -> ux_device_class_instance = (VOID *) asix; + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(asix -> ux_host_class_asix_class, (VOID *) asix); + + /* Configure the asix class. */ + status = _ux_host_class_asix_configure(asix); + + /* Get the asix endpoint(s). We need to search for Bulk Out and Bulk In endpoints + and the interrupt endpoint. */ + if (status == UX_SUCCESS) + status = _ux_host_class_asix_endpoints_get(asix); + + /* Create the semaphore to protect 2 threads from accessing the same asix instance. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&asix -> ux_host_class_asix_semaphore, "ux_host_class_asix_semaphore", 1); + if (status != UX_SUCCESS) + status = UX_SEMAPHORE_ERROR; + } + + /* Create the semaphore to wake up the Asix thread. */ + if(status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&asix -> ux_host_class_asix_interrupt_notification_semaphore, "ux_host_class_asix_interrupt_notification_semaphore", 0); + if (status != UX_SUCCESS) + status = UX_SEMAPHORE_ERROR; + } + + /* Allocate a Thread stack. */ + if (status == UX_SUCCESS) + { + asix -> ux_host_class_asix_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check the completion status. */ + if (asix -> ux_host_class_asix_thread_stack == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Create the asix class thread. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_thread_create(&asix -> ux_host_class_asix_thread, + "ux_asix_thread", _ux_host_class_asix_thread, + (ULONG) asix, + asix -> ux_host_class_asix_thread_stack, + UX_THREAD_STACK_SIZE, + UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, + TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check the completion status. */ + if (status != UX_SUCCESS) + status = UX_THREAD_ERROR; + } + + UX_THREAD_EXTENSION_PTR_SET(&(asix -> ux_host_class_asix_thread), asix) + + /* The asix chip needs to be setup properly. */ + if (status == UX_SUCCESS) + status = _ux_host_class_asix_setup(asix); + + /* Go on if there is no error. */ + if (status == UX_SUCCESS) + { + + /* The ethernet link is down by default. */ + asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_DOWN; + + /* Start the interrupt pipe now. */ + transfer_request = &asix -> ux_host_class_asix_interrupt_endpoint -> ux_endpoint_transfer_request; + status = _ux_host_stack_transfer_request(transfer_request); + } + + /* Allocate some packet pool for reception. */ + if (status == UX_SUCCESS) + { + + /* UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE overflow has been checked by + * UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT outside of function. + */ + asix -> ux_host_class_asix_pool_memory = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE); + if (asix -> ux_host_class_asix_pool_memory == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Create a packet pool. */ + if (status == UX_SUCCESS) + { + status = nx_packet_pool_create(&asix -> ux_host_class_asix_packet_pool, "Asix Packet Pool", + UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE, asix -> ux_host_class_asix_pool_memory, UX_HOST_CLASS_ASIX_NX_ETHERNET_POOL_ALLOCSIZE); + + /* Check for pool creation error. */ + if (status) + status = UX_ERROR; + } + + /* Do final things if success. */ + if (status == UX_SUCCESS) + { + + /* Mark the asix instance as live now. */ + asix -> ux_host_class_asix_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, asix -> ux_host_class_asix_class, (VOID *) asix); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_ASIX_ACTIVATE, asix, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, asix, 0, 0, 0) + + /* Return completion status. */ + return(UX_SUCCESS); + } + + /* There was a problem, so free the resources. */ + + /* Last resource, asix -> ux_host_class_asix_packet_pool is not created or created error, + no need to free. */ + + /* Free asix -> ux_host_class_asix_pool_memory. */ + if (asix -> ux_host_class_asix_pool_memory) + _ux_utility_memory_free(asix -> ux_host_class_asix_pool_memory); + + /* Free asix -> ux_host_class_asix_thread. */ + if (asix -> ux_host_class_asix_thread.tx_thread_id) + _ux_utility_thread_delete(&asix -> ux_host_class_asix_thread); + + /* Free asix -> ux_host_class_asix_thread_stack. */ + if (asix -> ux_host_class_asix_thread_stack) + _ux_utility_memory_free(asix -> ux_host_class_asix_thread_stack); + + /* Free asix -> ux_host_class_asix_interrupt_notification_semaphore. */ + if (asix -> ux_host_class_asix_interrupt_notification_semaphore.tx_semaphore_id != 0) + _ux_utility_semaphore_delete(&asix -> ux_host_class_asix_interrupt_notification_semaphore); + + /* Free asix -> ux_host_class_asix_semaphore. */ + if (asix -> ux_host_class_asix_semaphore.tx_semaphore_id != 0) + _ux_utility_semaphore_delete(&asix -> ux_host_class_asix_semaphore); + + /* Destroy class instance. */ + _ux_host_stack_class_instance_destroy(asix -> ux_host_class_asix_class, (VOID *) asix); + + /* Detach instance. */ + device -> ux_device_class_instance = UX_NULL; + + /* Free instance memory. */ + _ux_utility_memory_free(asix); + + /* Return completion status. */ + return(status); +#endif +} + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_configure.c b/common/usbx_host_classes/src/ux_host_class_asix_configure.c new file mode 100644 index 0000000..7e6f2c6 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_configure.c @@ -0,0 +1,153 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Asix Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to the */ +/* asix. Once the asix is configured, its interface will be */ +/* activated. The bulk endpoints (1 IN, 1 OUT ) and the optional */ +/* interrupt endpoint are enumerated. */ +/* */ +/* INPUT */ +/* */ +/* asix Pointer to asix class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get Get interface */ +/* _ux_host_stack_device_configuration_get Get configuration */ +/* _ux_host_stack_device_configuration_select Select configuration */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_asix_activate Asix class activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_asix_configure(UX_HOST_CLASS_ASIX *asix) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_DEVICE *parent_device; + + + /* If the device has been configured already, we don't need to do it + again. */ + if (asix -> ux_host_class_asix_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* A asix normally has one configuration. So retrieve the 1st configuration + only. */ + status = _ux_host_stack_device_configuration_get(asix -> ux_host_class_asix_device, 0, &configuration); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, asix -> ux_host_class_asix_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check the asix power source and check the parent power source for + incompatible connections. */ + if (asix -> ux_host_class_asix_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* Get parent device pointer. */ + parent_device = asix -> ux_host_class_asix_device -> ux_device_parent; + + /* If the device is NULL, the parent is the root asix and we don't have to worry + if the parent is not the root asix, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, asix, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration. */ + status = _ux_host_stack_device_configuration_select(configuration); + if (status != UX_SUCCESS) + return(status); + + /* If the operation went well, the asix default alternate setting for the asix interface is + active and the interrupt endpoint is now enabled. We have to memorize the first interface since + the interrupt endpoint is hooked to it. */ + status = _ux_host_stack_configuration_interface_get(configuration, 0, 0, &asix -> ux_host_class_asix_interface); + + /* Check status for error. */ + if (status == UX_SUCCESS) + { + + /* Store the instance in the interface container, this is for the USB stack + when it needs to invoke the class. */ + asix -> ux_host_class_asix_interface -> ux_interface_class_instance = (VOID *) asix; + + /* Store the class container in the interface. The device has the correct class, duplicate it to the + interface. */ + asix -> ux_host_class_asix_interface -> ux_interface_class = asix -> ux_host_class_asix_device -> ux_device_class ; + + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_deactivate.c b/common/usbx_host_classes/src/ux_host_class_asix_deactivate.c new file mode 100644 index 0000000..349e785 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_deactivate.c @@ -0,0 +1,216 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Asix Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the asix has been */ +/* removed from the bus either directly or indirectly. The bulk in\out */ +/* and interrupt pipes will be destroyed and the instance */ +/* removed. */ +/* */ +/* INPUT */ +/* */ +/* command Asix class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_utility_thread_delete Delete thread */ +/* _ux_network_driver_deactivate Deactivate NetX USB interface */ +/* nx_packet_transmit_release Release NetX packet */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_asix_entry Entry of asix class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_asix_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_ASIX *asix; +UX_TRANSFER *transfer_request; +NX_PACKET *current_packet; +NX_PACKET *next_packet; +UINT status; + + /* Get the instance for this class. */ + asix = (UX_HOST_CLASS_ASIX *) command -> ux_host_class_command_instance; + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&asix -> ux_host_class_asix_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* The asix is being shut down. */ + asix -> ux_host_class_asix_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + + /* Check if link was up. */ + if (asix -> ux_host_class_asix_link_state == UX_HOST_CLASS_ASIX_LINK_STATE_UP) + { + /* We need to free the packets that will not be sent. */ + current_packet = asix -> ux_host_class_asix_xmit_queue; + + /* Get the next packet associated with the first packet. */ + next_packet = current_packet -> nx_packet_queue_next; + + /* Parse all these packets that were scheduled. */ + while (current_packet != UX_NULL) + { + + /* Free the packet that was just sent. First do some housekeeping. */ + current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_HOST_CLASS_ASIX_ETHERNET_SIZE; + current_packet -> nx_packet_length = current_packet -> nx_packet_length - UX_HOST_CLASS_ASIX_ETHERNET_SIZE; + + /* And ask Netx to release it. */ + nx_packet_transmit_release(current_packet); + + /* Next packet becomes the current one. */ + current_packet = next_packet; + + /* Next packet now. */ + if (current_packet != UX_NULL) + + /* Get the next packet associated with the first packet. */ + next_packet = current_packet -> nx_packet_queue_next; + + } + + } + + /* Now the link is down. */ + asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_DOWN; + + /* Deregister this interface to the NetX USB interface broker. */ + status = _ux_network_driver_deactivate((VOID *) asix, asix -> ux_host_class_asix_network_handle); + + /* If the interrupt endpoint is defined, clean any pending transfer. */ + if (asix -> ux_host_class_asix_interrupt_endpoint != UX_NULL) + { + + /* Wait for any current transfer to be out of pending. */ + transfer_request = &asix -> ux_host_class_asix_interrupt_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + + /* And abort any transfer. */ + _ux_host_stack_endpoint_transfer_abort(asix -> ux_host_class_asix_interrupt_endpoint); + + /* And free the memory used by the interrupt endpoint. */ + _ux_utility_memory_free(transfer_request -> ux_transfer_request_data_pointer); + + } + + /* First we take care of cleaning endpoint IN. */ + transfer_request = &asix -> ux_host_class_asix_bulk_in_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(asix -> ux_host_class_asix_bulk_in_endpoint); + + /* Then endpoint OUT. */ + transfer_request = &asix -> ux_host_class_asix_bulk_out_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + + /* We need to abort transactions on the bulk Out pipe. We normally don't need that anymore. */ + _ux_host_stack_endpoint_transfer_abort(asix -> ux_host_class_asix_bulk_out_endpoint); + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(asix -> ux_host_class_asix_class, (VOID *) asix); + + /* Destroy the semaphores. */ + _ux_utility_semaphore_delete(&asix -> ux_host_class_asix_semaphore); + _ux_utility_semaphore_delete(&asix -> ux_host_class_asix_interrupt_notification_semaphore); + + /* Destroy the link monitoring thread. */ + _ux_utility_thread_delete(&asix -> ux_host_class_asix_thread); + + /* free its stack memory. */ + _ux_utility_memory_free(asix -> ux_host_class_asix_thread_stack); + + /* We may have allocated a packet pool. */ + if (asix -> ux_host_class_asix_pool_memory != UX_NULL) + + /* Free this pool of packets. */ + _ux_utility_memory_free(asix -> ux_host_class_asix_pool_memory); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, asix -> ux_host_class_asix_class, (VOID *) asix); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_ASIX_DEACTIVATE, asix, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(asix); + + /* Free the asix instance memory. */ + _ux_utility_memory_free(asix); + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_asix_endpoints_get.c new file mode 100644 index 0000000..aef3b24 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_endpoints_get.c @@ -0,0 +1,267 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Asix Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function distinguishes for either the Data or Control Class. */ +/* For the data class, we mount the bulk in and bulk out endpoints. */ +/* For the control class, we mount the optional interrupt endpoint. */ +/* */ +/* INPUT */ +/* */ +/* asix Pointer to asix class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_utility_memory_allocate Allocate memory */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_asix_activate Activate asix class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_asix_endpoints_get(UX_HOST_CLASS_ASIX *asix) +{ + +UINT status; +UINT endpoint_index; +UX_ENDPOINT *endpoint; +UX_TRANSFER *transfer_request; + + + /* Search the bulk OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < asix -> ux_host_class_asix_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get interface endpoint. */ + status = _ux_host_stack_interface_endpoint_get(asix -> ux_host_class_asix_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the OUT direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + + + /* There is a callback function associated with the transfer request, so we need the class instance. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_class_instance = (VOID *) asix; + + /* The transfer request has a callback function. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_completion_function = _ux_host_class_asix_transmission_callback; + + /* We have found the bulk endpoint, save it. */ + asix -> ux_host_class_asix_bulk_out_endpoint = endpoint; + break; + } + } + } + + /* The bulk out endpoint is mandatory. */ + if (asix -> ux_host_class_asix_bulk_out_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, asix, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search the bulk IN endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < asix -> ux_host_class_asix_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + status = _ux_host_stack_interface_endpoint_get(asix -> ux_host_class_asix_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* There is a callback function associated with the transfer request, so we need the class instance. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_class_instance = (VOID *) asix; + + /* The transfer request has a callback function. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_completion_function = _ux_host_class_asix_reception_callback; + + /* We have found the bulk endpoint, save it. */ + asix -> ux_host_class_asix_bulk_in_endpoint = endpoint; + break; + } + } + } + + /* The bulk in endpoint is mandatory. */ + if (asix -> ux_host_class_asix_bulk_in_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, asix, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search the Interrupt endpoint. It is mandatory. */ + for (endpoint_index = 0; endpoint_index < asix -> ux_host_class_asix_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + status = _ux_host_stack_interface_endpoint_get(asix -> ux_host_class_asix_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is Interrupt and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the interrupt endpoint, save it. */ + asix -> ux_host_class_asix_interrupt_endpoint = endpoint; + + /* The endpoint is correct, Fill in the transfer request with the length requested for this endpoint. */ + transfer_request = &asix -> ux_host_class_asix_interrupt_endpoint -> ux_endpoint_transfer_request; + transfer_request -> ux_transfer_request_requested_length = asix -> ux_host_class_asix_interrupt_endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + transfer_request -> ux_transfer_request_actual_length = 0; + + /* The direction is always IN for the CDC interrupt endpoint. */ + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN; + + /* There is a callback function associated with the transfer request, so we need the class instance. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) asix; + + /* Interrupt transactions have a completion routine. */ + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_asix_interrupt_notification; + + /* Obtain a buffer for this transaction. The buffer will always be reused. */ + transfer_request -> ux_transfer_request_data_pointer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + transfer_request -> ux_transfer_request_requested_length); + + /* If the endpoint is available and we have memory, we start the interrupt endpoint. */ + if (transfer_request -> ux_transfer_request_data_pointer != UX_NULL) + { + + /* The transfer on the interrupt endpoint can be started. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check error, if endpoint interrupt IN transfer not successful, do not proceed. */ + if (status != UX_SUCCESS) + + /* Error, do not proceed. */ + return(status); + + } + + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We must return an error. */ + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + break; + } + } + } + + /* The interrupt endpoint is mandatory. */ + if (asix -> ux_host_class_asix_interrupt_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, asix, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + else + + /* All endpoints have been mounted. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_entry.c b/common/usbx_host_classes/src/ux_host_class_asix_entry.c new file mode 100644 index 0000000..aeed0ca --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_entry.c @@ -0,0 +1,132 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Asix Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the asix class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* asix ethernet device on the bus or when the it is removed. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* command Asix class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_asix_activate Activate asix class */ +/* _ux_host_class_asix_deactivate Deactivate asix class */ +/* */ +/* CALLED BY */ +/* */ +/* Asix Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_asix_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if(command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_PIDVID) + { + + /* Try all the possible PID/VID. */ + if ((command -> ux_host_class_command_pid == UX_HOST_CLASS_ASIX_PRODUCT_ID) && + (command -> ux_host_class_command_vid == UX_HOST_CLASS_ASIX_VENDOR_ID )) + return(UX_SUCCESS); + + /* Try all the possible PID/VID. */ + if ((command -> ux_host_class_command_pid == UX_HOST_CLASS_ASIX_PRODUCT_FUJIEI_ID) && + (command -> ux_host_class_command_vid == UX_HOST_CLASS_ASIX_VENDOR_FUJIEI_ID )) + return(UX_SUCCESS); + + } + + /* No match. */ + return(UX_NO_CLASS_MATCH); + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_asix_activate(command); + return(status); + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_asix_deactivate(command); + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_interrupt_notification.c b/common/usbx_host_classes/src/ux_host_class_asix_interrupt_notification.c new file mode 100644 index 0000000..706c5dc --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_interrupt_notification.c @@ -0,0 +1,189 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** ASIX Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_interrupt_notification PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the stack when an interrupt packet as */ +/* been received. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_host_stack_transfer_request Transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* USBX stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_asix_interrupt_notification(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_ASIX *asix; + + /* Get the class instance for this transfer request. */ + asix = (UX_HOST_CLASS_ASIX *) transfer_request -> ux_transfer_request_class_instance; + + /* Check the state of the transfer. If there is an error, we do not proceed with this notification. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + + /* We do not proceed. */ + return; + + /* Check if the class is in shutdown. */ + if (asix -> ux_host_class_asix_state == UX_HOST_CLASS_INSTANCE_SHUTDOWN) + + /* We do not proceed. */ + return; + + /* Increment the notification count. */ + asix -> ux_host_class_asix_notification_count++; + + /* Ensure the length of our interrupt pipe data is correct. */ + if (transfer_request -> ux_transfer_request_actual_length == + asix -> ux_host_class_asix_interrupt_endpoint -> ux_endpoint_descriptor.wMaxPacketSize) + { + + /* Check if the first byte is a interrupt packet signature. */ + if (*(transfer_request -> ux_transfer_request_data_pointer + UX_HOST_CLASS_ASIX_INTERRUPT_SIGNATURE_OFFSET) == + UX_HOST_CLASS_ASIX_INTERRUPT_SIGNATURE_VALUE) + { + + /* Explore the content of the interrupt packet. We treat the link up/down flag here. */ + if (*(transfer_request -> ux_transfer_request_data_pointer + UX_HOST_CLASS_ASIX_INTERRUPT_STATE_OFFSET) & + UX_HOST_CLASS_ASIX_INTERRUPT_STATE_PPLS) + { + + /* Link is up. See if we know about that. */ + if (asix -> ux_host_class_asix_link_state != UX_HOST_CLASS_ASIX_LINK_STATE_UP && + asix -> ux_host_class_asix_link_state != UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_UP) + { + + /* Memorize the new link state. */ + asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_UP; + + /* We need to inform the asix thread of this change. */ + _ux_utility_semaphore_put(&asix -> ux_host_class_asix_interrupt_notification_semaphore); + + } + } + else + { + + /* Link is down. See if we know about that. */ + if (asix -> ux_host_class_asix_link_state != UX_HOST_CLASS_ASIX_LINK_STATE_DOWN && + asix -> ux_host_class_asix_link_state != UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_DOWN) + { + + /* Memorize the new link state. */ + asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_DOWN; + + /* We may have transaction pending on bulk in. Inform the class. */ + transfer_request = &asix -> ux_host_class_asix_bulk_in_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + { + + /* Set the completion error code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_NO_ANSWER; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Wake up the semaphore on which the transaction is waiting. */ + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + + } + + /* We may have transaction pending on bulk out. Inform the class. */ + transfer_request = &asix -> ux_host_class_asix_bulk_out_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + { + + /* Set the completion error code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_NO_ANSWER; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_NO_ANSWER); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Wake up the semaphore on which the transaction is waiting. */ + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + + } + + + /* We need to inform the asix thread of this change. */ + _ux_utility_semaphore_put(&asix -> ux_host_class_asix_interrupt_notification_semaphore); + } + } + } + } + + /* Reactivate the ASIX interrupt pipe. */ + _ux_host_stack_transfer_request(transfer_request); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_ASIX_INTERRUPT_NOTIFICATION, asix, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_read.c b/common/usbx_host_classes/src/ux_host_class_asix_read.c new file mode 100644 index 0000000..643c625 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_read.c @@ -0,0 +1,181 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Asix Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the asix interface. The call is */ +/* blocking and only returns when there is either an error or when */ +/* the transfer is complete. */ +/* */ +/* INPUT */ +/* */ +/* asix Pointer to asix class */ +/* data_pointer Pointer to buffer */ +/* requested_length Requested data read */ +/* actual_length Actual data read */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_asix_read (UX_HOST_CLASS_ASIX *asix, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_ASIX_READ, asix, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (asix -> ux_host_class_asix_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, asix, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Start by resetting the actual length of the transfer to zero. */ + *actual_length = 0; + + /* Get the pointer to the bulk in endpoint in the transfer_request. */ + transfer_request = &asix -> ux_host_class_asix_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Perform a transfer on the bulk in endpoint until either the transfer is + completed or until there is an error. */ + while (requested_length) + { + + /* Program the maximum authorized length for this transfer request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer_request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_ASIX_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer request in case some data was actually received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* There was an error, return to the caller */ + return(UX_TRANSFER_ERROR); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked. */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion status. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + return(transfer_request -> ux_transfer_request_completion_code); + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually received and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Return success to caller. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to receive. */ + requested_length -= transfer_request_length; + } + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_reception_callback.c b/common/usbx_host_classes/src/ux_host_class_asix_reception_callback.c new file mode 100644 index 0000000..87d2fa4 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_reception_callback.c @@ -0,0 +1,158 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Asix Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_reception_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the callback from the USBX transfer functions, */ +/* it is called when a full or partial transfer has been done for a */ +/* bulk in transfer. It calls back the application. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_short_get_big_endian Get 16-bit big endian */ +/* _ux_network_driver_packet_received Process received packet */ +/* nx_packet_transmit_release Release NetX packet */ +/* nx_packet_allocate Allocate NetX packet */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_asix_reception_callback (UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_ASIX *asix; +NX_PACKET *packet; +ULONG ip_given_length; +UINT status; + + /* Get the class instance for this transfer request. */ + asix = (UX_HOST_CLASS_ASIX *) transfer_request -> ux_transfer_request_class_instance; + + /* Load the packet that is associated with this reception. */ + packet = transfer_request -> ux_transfer_request_user_specific; + + /* Check the state of the transfer. If there is an error, we do not proceed with this report. */ + if (transfer_request -> ux_transfer_request_completion_code == UX_SUCCESS) + { + + /* Adjust the prepend, length, append fields to take the Ether header out */ + packet -> nx_packet_prepend_ptr += 4; + packet -> nx_packet_length = transfer_request -> ux_transfer_request_actual_length - 4; + packet -> nx_packet_append_ptr = + packet->nx_packet_prepend_ptr + transfer_request -> ux_transfer_request_actual_length ; + + /* Calculate the accurate packet length from ip header */ + if((*(packet -> nx_packet_prepend_ptr + 12) == 0x08) && + (*(packet -> nx_packet_prepend_ptr + 13) == 0)) + { + ip_given_length = _ux_utility_short_get_big_endian(packet -> nx_packet_prepend_ptr + 16) + UX_HOST_CLASS_ASIX_ETHERNET_SIZE; + packet->nx_packet_length = ip_given_length ; + packet->nx_packet_append_ptr = packet->nx_packet_prepend_ptr + ip_given_length; + } + + /* Send that packet to the NetX USB broker. */ + _ux_network_driver_packet_received(asix -> ux_host_class_asix_network_handle, packet); + + } + + else + + /* Free the packet that was not successfully received. */ + nx_packet_transmit_release(packet); + + /* We can accept new reception. Get a NX Packet */ + if (nx_packet_allocate(&asix -> ux_host_class_asix_packet_pool, &packet, + NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_SUCCESS) + { + + /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ + packet -> nx_packet_prepend_ptr += sizeof(USHORT); + + /* Set the data pointer. */ + transfer_request -> ux_transfer_request_data_pointer = packet -> nx_packet_prepend_ptr; + + /* And length. */ + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE; + transfer_request -> ux_transfer_request_actual_length = 0; + + /* Store the packet that owns this transaction. */ + transfer_request -> ux_transfer_request_user_specific = packet; + + /* Memorize this packet at the beginning of the queue. */ + asix -> ux_host_class_asix_receive_queue = packet; + + /* Reset the queue pointer of this packet. */ + packet -> nx_packet_queue_next = UX_NULL; + + /* Ask USB to schedule a reception. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check if the transaction was armed successfully. We do not wait for the packet to be sent here. */ + if (status != UX_SUCCESS) + { + + /* Cancel the packet. */ + asix -> ux_host_class_asix_receive_queue = UX_NULL; + + } + } + /* There is no status to be reported back to the stack. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_setup.c b/common/usbx_host_classes/src/ux_host_class_asix_setup.c new file mode 100644 index 0000000..d4c8770 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_setup.c @@ -0,0 +1,642 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Asix Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_setup PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function prepares the Asix chip Phy and rx and xmit registers. */ +/* */ +/* INPUT */ +/* */ +/* asix Pointer to asix class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_asix_activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_asix_setup(UX_HOST_CLASS_ASIX *asix) +{ + +UCHAR *setup_buffer; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +ULONG phy_register_value; +UINT status; + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &asix -> ux_host_class_asix_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the buffer. */ + setup_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_ASIX_SETUP_BUFFER_SIZE); + if (setup_buffer == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Get the Ethernet Phy Address register. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_READ_PHY_ID; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if ((status != UX_SUCCESS) || (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) || + (transfer_request -> ux_transfer_request_actual_length != 2)) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Extract the PHY IDs and the type. */ + asix -> ux_host_class_asix_primary_phy_id = *(setup_buffer + UX_HOST_CLASS_ASIX_PHY_ID_PRIMARY) & UX_HOST_CLASS_ASIX_PHY_ID_MASK; + asix -> ux_host_class_asix_primary_phy_type = (*(setup_buffer + UX_HOST_CLASS_ASIX_PHY_ID_PRIMARY) >> UX_HOST_CLASS_ASIX_PHY_TYPE_SHIFT) & UX_HOST_CLASS_ASIX_PHY_TYPE_MASK; + + asix -> ux_host_class_asix_secondary_phy_id = *(setup_buffer + UX_HOST_CLASS_ASIX_PHY_ID_SECONDARY) & UX_HOST_CLASS_ASIX_PHY_ID_MASK; + asix -> ux_host_class_asix_secondary_phy_type = (*(setup_buffer + UX_HOST_CLASS_ASIX_PHY_ID_SECONDARY) >> UX_HOST_CLASS_ASIX_PHY_TYPE_SHIFT) & UX_HOST_CLASS_ASIX_PHY_TYPE_MASK; + + /* Set the GPIO 2 register. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_GPIO_STATUS; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = (UX_HOST_CLASS_ASIX_GPIO_RSE | UX_HOST_CLASS_ASIX_GPIO_GPO2EN | UX_HOST_CLASS_ASIX_GPIO_GPO_2); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Set the Software PHY Select register. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_SW_PHY_SELECT_STATUS; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 1; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Perform a software reset of IPPD. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_SW_RESET; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_ASIX_SW_RESET_IPPD; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Perform a software reset. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_SW_RESET; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + + /* Perform a software reset of IPRL and PRL. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_SW_RESET; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = (UX_HOST_CLASS_ASIX_SW_RESET_IPRL | UX_HOST_CLASS_ASIX_SW_RESET_PRL); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Write the value of the Receive Control register. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_RX_CTL; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = UX_HOST_CLASS_ASIX_RXCR_MFB_2048; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Get the Ethernet Phy Address register. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_ASIX_NODE_ID_LENGTH; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_READ_NODE_ID; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || + transfer_request -> ux_transfer_request_actual_length != UX_HOST_CLASS_ASIX_NODE_ID_LENGTH) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + + /* Copy the node id into the Asix instance. */ + _ux_utility_memory_copy(asix -> ux_host_class_asix_node_id, setup_buffer, UX_HOST_CLASS_ASIX_NODE_ID_LENGTH); + + /* Request ownership of Serial Management Interface. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_OWN_SMI ; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + + /* Get the value of the PHYIDR1 in the PHY register. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_READ_PHY_REG; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = asix -> ux_host_class_asix_primary_phy_id; + transfer_request -> ux_transfer_request_index = UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || + transfer_request -> ux_transfer_request_actual_length != 2) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Extract the Vendor model number and model revision number. First get the value + in proper 16 bit little endian. */ + phy_register_value = _ux_utility_short_get(setup_buffer); + + /* Get the model revision number. */ + asix -> ux_host_class_asix_model_revision_number = (phy_register_value >> UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_MDL_REV_SHIFT) & UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_MDL_REV_MASK; + + /* Get the vendor model number. */ + asix -> ux_host_class_asix_vendor_model_number = (phy_register_value >> UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_VNDR_REV_SHIFT) & UX_HOST_CLASS_ASIX_PHY_REG_PHYIDR1_VNDR_REV_MASK ; + + + /* Perform a software reset. External Phy Reset Pin level. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_SW_RESET; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_ASIX_SW_RESET_PRL; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Perform a software reset. Internal Phy reset Control and external Phy Reset Pin level. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_SW_RESET; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = (UX_HOST_CLASS_ASIX_SW_RESET_IPRL | UX_HOST_CLASS_ASIX_SW_RESET_PRL); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + + /* Write the value of the BMCR register in the PHY register. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_PHY_REG; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = asix -> ux_host_class_asix_primary_phy_id; + transfer_request -> ux_transfer_request_index = UX_HOST_CLASS_ASIX_PHY_REG_BMCR; + + /* Set the value for the PHY reg. */ + phy_register_value = UX_HOST_CLASS_ASIX_PHY_REG_BMCR_RESET; + + /* Insert the value into the target buffer. */ + _ux_utility_short_put(setup_buffer, (USHORT)phy_register_value); + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || + transfer_request -> ux_transfer_request_actual_length != 2) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + + /* Read the value of the BMCR register in the PHY register. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_READ_PHY_REG; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = asix -> ux_host_class_asix_primary_phy_id; + transfer_request -> ux_transfer_request_index = UX_HOST_CLASS_ASIX_PHY_REG_BMCR; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || transfer_request -> ux_transfer_request_actual_length != 2) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Extract the speed selected by the PHY. */ + phy_register_value = _ux_utility_short_get(setup_buffer); + + /* Isolate the speed and memorize it. */ + if (phy_register_value & UX_HOST_CLASS_ASIX_PHY_REG_BMCR_SPEED_100MBS) + + /* Select 100 MBPS as our speed. */ + asix -> ux_host_class_asix_speed_selected = UX_HOST_CLASS_ASIX_SPEED_SELECTED_100MPBS; + + else + + /* Select 10 MBPS as our speed. */ + asix -> ux_host_class_asix_speed_selected = UX_HOST_CLASS_ASIX_SPEED_SELECTED_10MPBS; + + /* Set the value of the ANAR in the PHY register. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_PHY_REG; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = asix -> ux_host_class_asix_primary_phy_id; + transfer_request -> ux_transfer_request_index = UX_HOST_CLASS_ASIX_PHY_REG_ANAR; + + /* Set the value for the PHY reg. */ + phy_register_value = (UX_HOST_CLASS_ASIX_PHY_REG_ANAR_DEFAULT_SELECTOR | + UX_HOST_CLASS_ASIX_PHY_REG_ANAR_10_HD | + UX_HOST_CLASS_ASIX_PHY_REG_ANAR_10_FD | + UX_HOST_CLASS_ASIX_PHY_REG_ANAR_TX_HD | + UX_HOST_CLASS_ASIX_PHY_REG_ANAR_TX_FD | + UX_HOST_CLASS_ASIX_PHY_REG_ANAR_PAUSE); + + /* Insert the value into the target buffer. */ + _ux_utility_short_put(setup_buffer, (USHORT)phy_register_value); + + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || + transfer_request -> ux_transfer_request_actual_length != 2) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Set the value of the BMCR in the PHY register. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_PHY_REG; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = asix -> ux_host_class_asix_primary_phy_id; + transfer_request -> ux_transfer_request_index = UX_HOST_CLASS_ASIX_PHY_REG_BMCR; + + /* Check speed. */ + if (asix -> ux_host_class_asix_speed_selected == UX_HOST_CLASS_ASIX_SPEED_SELECTED_100MPBS) + + /* Set speed at 100MBPS. */ + phy_register_value = UX_HOST_CLASS_ASIX_PHY_REG_BMCR_SPEED_100MBS; + + /* Set the value for the PHY reg. */ + phy_register_value |= (UX_HOST_CLASS_ASIX_PHY_REG_BMCR_AUTO_NEGOTIATION | UX_HOST_CLASS_ASIX_PHY_REG_BMCR_RESTART_NEG | + UX_HOST_CLASS_ASIX_PHY_REG_BMCR_DUPLEX_MODE); + + /* Insert the value into the target buffer. */ + _ux_utility_short_put(setup_buffer, (USHORT)phy_register_value); + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || + transfer_request -> ux_transfer_request_actual_length != 2) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + + /* Check speed. */ + if (asix -> ux_host_class_asix_speed_selected == UX_HOST_CLASS_ASIX_SPEED_SELECTED_100MPBS) + + /* Set speed at 100MBPS. */ + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_ASIX_MEDIUM_PS; + + /* Write the value of the Medium Mode. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_MEDIUM_MODE; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value |= (UX_HOST_CLASS_ASIX_MEDIUM_FD | UX_HOST_CLASS_ASIX_MEDIUM_BIT2 | UX_HOST_CLASS_ASIX_MEDIUM_RFC_ENABLED | + UX_HOST_CLASS_ASIX_MEDIUM_TFC_ENABLED | UX_HOST_CLASS_ASIX_MEDIUM_RE_ENABLED); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + + /* Write the value of the IPG0/IPG1/IPG2. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_IPG012; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_ASIX_PPG0_IPG1; + transfer_request -> ux_transfer_request_index = UX_HOST_CLASS_ASIX_PPG2; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Release SMI ownership. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_RELEASE_SMI; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Set the Rx Control register value. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_RX_CTL; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = (UX_HOST_CLASS_ASIX_RXCR_AB | UX_HOST_CLASS_ASIX_RXCR_SO | UX_HOST_CLASS_ASIX_RXCR_MFB_2048); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_thread.c b/common/usbx_host_classes/src/ux_host_class_asix_thread.c new file mode 100644 index 0000000..02615fd --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_thread.c @@ -0,0 +1,420 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** ASIX Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This is the Asix thread that monitors the link change flag. */ +/* */ +/* INPUT */ +/* */ +/* asix Asix instance */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_memory_set Set memory */ +/* _ux_network_driver_activate Activate NetX USB interface */ +/* _ux_network_driver_link_down Set state to link down */ +/* _ux_network_driver_link_up Set state to link up */ +/* nx_packet_allocate Allocate NetX packet */ +/* nx_packet_transmit_release Release NetX packet */ +/* */ +/* CALLED BY */ +/* */ +/* Asix class initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_asix_thread(ULONG parameter) +{ + +UX_HOST_CLASS_ASIX *asix; +UCHAR *setup_buffer; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +NX_PACKET *packet; +NX_PACKET *current_packet; +NX_PACKET *next_packet; +UINT status; +ULONG physical_address_msw; +ULONG physical_address_lsw; + + /* Cast the parameter passed in the thread into the asix pointer. */ + UX_THREAD_EXTENSION_PTR_GET(asix, UX_HOST_CLASS_ASIX, parameter) + + /* Loop forever waiting for changes signaled through the semaphore. */ + while (1) + { + + /* Wait for the semaphore to be put by the asix interrupt event. */ + status = _ux_utility_semaphore_get(&asix -> ux_host_class_asix_interrupt_notification_semaphore, UX_WAIT_FOREVER); + + /* Check for successful completion. */ + if (status != UX_SUCCESS) + + return; + + /* Protect Thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&asix -> ux_host_class_asix_semaphore, UX_WAIT_FOREVER); + + /* Check for successful completion. */ + if (status != UX_SUCCESS) + + return; + + /* Check the link state. It is either pending up or down. */ + if (asix -> ux_host_class_asix_link_state == UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_UP) + { + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &asix -> ux_host_class_asix_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the buffer. */ + setup_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_ASIX_SETUP_BUFFER_SIZE); + if (setup_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + + return; + } + + /* Request ownership of Serial Management Interface. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_OWN_SMI ; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + + /* Return completion status. */ + return; + + } + + /* Get the value of the PHYIDR1 in the PHY register. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_READ_PHY_REG; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = asix -> ux_host_class_asix_primary_phy_id; + transfer_request -> ux_transfer_request_index = UX_HOST_CLASS_ASIX_PHY_REG_ANLPAR; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || + transfer_request -> ux_transfer_request_actual_length != 2) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + + /* Return completion status. */ + return; + + } + + /* Release SMI ownership. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_RELEASE_SMI; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + + /* Return completion status. */ + return; + + } + + /* Check speed. */ + if (asix -> ux_host_class_asix_speed_selected == UX_HOST_CLASS_ASIX_SPEED_SELECTED_100MPBS) + + /* Set speed at 100MBPS. */ + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_ASIX_MEDIUM_PS; + + /* Write the value of the Medium Mode. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_MEDIUM_MODE; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value |= (UX_HOST_CLASS_ASIX_MEDIUM_FD | UX_HOST_CLASS_ASIX_MEDIUM_BIT2 | UX_HOST_CLASS_ASIX_MEDIUM_RFC_ENABLED | + UX_HOST_CLASS_ASIX_MEDIUM_TFC_ENABLED | UX_HOST_CLASS_ASIX_MEDIUM_RE_ENABLED); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + + /* Return completion status. */ + return; + + } + + /* Set the Rx Control register value. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_RX_CTL; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = (UX_HOST_CLASS_ASIX_RXCR_AM | UX_HOST_CLASS_ASIX_RXCR_AB | + UX_HOST_CLASS_ASIX_RXCR_SO | UX_HOST_CLASS_ASIX_RXCR_MFB_2048); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + + /* Return completion status. */ + return; + + } + + /* Set the multicast value. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 8; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_ASIX_REQ_WRITE_MULTICAST_FILTER; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Fill in the multicast filter. */ + _ux_utility_memory_set(setup_buffer, 0, 8); + *(setup_buffer +1) = 0x40; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS || + transfer_request -> ux_transfer_request_actual_length != 8) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + + /* Return completion status. */ + return; + + } + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Setup the physical address of this IP instance. */ + physical_address_msw = (ULONG)((asix -> ux_host_class_asix_node_id[0] << 8) | (asix -> ux_host_class_asix_node_id[1])); + physical_address_lsw = (ULONG)((asix -> ux_host_class_asix_node_id[2] << 24) | (asix -> ux_host_class_asix_node_id[3] << 16) | + (asix -> ux_host_class_asix_node_id[4] << 8) | (asix -> ux_host_class_asix_node_id[5])); + + /* Register this interface to the NetX USB interface broker. */ + status = _ux_network_driver_activate((VOID *) asix, _ux_host_class_asix_write, + &asix -> ux_host_class_asix_network_handle, + physical_address_msw, + physical_address_lsw); + + /* Now the link is up. */ + asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_UP; + + /* Communicate the state with the network driver. */ + _ux_network_driver_link_up(asix -> ux_host_class_asix_network_handle); + + /* We can accept reception. Get a NX Packet */ + if (nx_packet_allocate(&asix -> ux_host_class_asix_packet_pool, &packet, + NX_RECEIVE_PACKET, NX_NO_WAIT) == NX_SUCCESS) + { + + + /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ + packet -> nx_packet_prepend_ptr += sizeof(USHORT); + + /* We have a packet. Link this packet to the reception transfer request on the bulk in endpoint. */ + transfer_request = &asix -> ux_host_class_asix_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Set the data pointer. */ + transfer_request -> ux_transfer_request_data_pointer = packet -> nx_packet_prepend_ptr; + + /* And length. */ + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_ASIX_NX_PAYLOAD_SIZE; + transfer_request -> ux_transfer_request_actual_length = 0; + + /* Store the packet that owns this transaction. */ + transfer_request -> ux_transfer_request_user_specific = packet; + + /* Memorize this packet at the beginning of the queue. */ + asix -> ux_host_class_asix_receive_queue = packet; + + /* Reset the queue pointer of this packet. */ + packet -> nx_packet_queue_next = UX_NULL; + + /* Ask USB to schedule a reception. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check if the transaction was armed successfully. We do not wait for the packet to be sent here. */ + if (status != UX_SUCCESS) + { + + /* Cancel the packet. */ + asix -> ux_host_class_asix_receive_queue = UX_NULL; + + } + + } + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + + return; + } + + /* Check the link state. It is either pending up or down. */ + if (asix -> ux_host_class_asix_link_state == UX_HOST_CLASS_ASIX_LINK_STATE_PENDING_DOWN) + { + + /* We need to free the packets that will not be sent. */ + current_packet = asix -> ux_host_class_asix_xmit_queue; + + /* Get the next packet associated with the first packet. */ + next_packet = current_packet -> nx_packet_queue_next; + + /* Parse all these packets that were scheduled. */ + while (current_packet != UX_NULL) + { + + /* Free the packet that was just sent. First do some housekeeping. */ + current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_HOST_CLASS_ASIX_ETHERNET_SIZE; + current_packet -> nx_packet_length = current_packet -> nx_packet_length - UX_HOST_CLASS_ASIX_ETHERNET_SIZE; + + /* And ask Netx to release it. */ + nx_packet_transmit_release(current_packet); + + /* Next packet becomes the current one. */ + current_packet = next_packet; + + /* Next packet now. */ + if (current_packet != UX_NULL) + + /* Get the next packet associated with the first packet. */ + next_packet = current_packet -> nx_packet_queue_next; + + } + + + /* Now the link is down. */ + asix -> ux_host_class_asix_link_state = UX_HOST_CLASS_ASIX_LINK_STATE_DOWN; + + /* Communicate the state with the network driver. */ + _ux_network_driver_link_down(asix -> ux_host_class_asix_network_handle); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&asix -> ux_host_class_asix_semaphore); + + return; + + } + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_transmission_callback.c b/common/usbx_host_classes/src/ux_host_class_asix_transmission_callback.c new file mode 100644 index 0000000..c1f6ce6 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_transmission_callback.c @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Asix Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_transmission_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the callback from the USBX transfer functions, */ +/* it is called when a full or partial transfer has been done for a */ +/* bulk out transfer. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_short_put Put 16-bit value */ +/* nx_packet_transmit_release Release NetX packet */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_asix_transmission_callback (UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_ASIX *asix; +NX_PACKET *current_packet; +NX_PACKET *next_packet; +UCHAR *packet_header; + + /* Get the class instance for this transfer request. */ + asix = (UX_HOST_CLASS_ASIX *) transfer_request -> ux_transfer_request_class_instance; + + /* Check the state of the transfer. If there is an error, we do not proceed with this report. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* We do not proceed. */ + return; + + } + + /* Check if the class is in shutdown. */ + if (asix -> ux_host_class_asix_state == UX_HOST_CLASS_INSTANCE_SHUTDOWN) + + /* We do not proceed. */ + return; + + /* Check if there is another transfer for this pipe. */ + current_packet = asix -> ux_host_class_asix_xmit_queue; + + /* Get the next packet associated with the first packet. */ + next_packet = current_packet -> nx_packet_queue_next; + + /* Set the next packet (or a NULL value) as the head of the xmit queue. */ + asix -> ux_host_class_asix_xmit_queue = next_packet; + + /* If there is nothing else or if the link is down no need to rearm a packet. */ + if (next_packet != UX_NULL && asix -> ux_host_class_asix_link_state == UX_HOST_CLASS_ASIX_LINK_STATE_UP) + { + + /* Load the address of the current packet header of the physical header. */ + packet_header = next_packet -> nx_packet_prepend_ptr; + + /* Substract 2 USHORT to store length of the packet. */ + packet_header -= sizeof(USHORT) * 2; + + /* Store the length of the payload in the first USHORT. */ + _ux_utility_short_put(packet_header, (USHORT)(next_packet -> nx_packet_length)); + + /* Store the negative length of the payload in the first USHORT. */ + _ux_utility_short_put(packet_header+ sizeof(USHORT), (USHORT)(~next_packet -> nx_packet_length)); + + /* Prepare the values for this new transmission. */ + transfer_request -> ux_transfer_request_data_pointer = packet_header; + transfer_request -> ux_transfer_request_requested_length = next_packet -> nx_packet_length + (ULONG)sizeof(USHORT) * 2; + + /* Store the packet that owns this transaction. */ + transfer_request -> ux_transfer_request_user_specific = next_packet; + + /* Arm another transfer. */ + _ux_host_stack_transfer_request(transfer_request); + } + + /* Free the packet that was just sent. First do some housekeeping. */ + current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_HOST_CLASS_ASIX_ETHERNET_SIZE; + current_packet -> nx_packet_length = current_packet -> nx_packet_length - UX_HOST_CLASS_ASIX_ETHERNET_SIZE; + + /* And ask Netx to release it. */ + nx_packet_transmit_release(current_packet); + + /* There is no status to be reported back to the stack. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_asix_write.c b/common/usbx_host_classes/src/ux_host_class_asix_write.c new file mode 100644 index 0000000..dfe33c6 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_asix_write.c @@ -0,0 +1,195 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Asix Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_asix.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_asix_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the asix interface. The call is blocking */ +/* and only returns when there is either an error or when the transfer */ +/* is complete. */ +/* */ +/* INPUT */ +/* */ +/* asix Pointer to asix class */ +/* packet Packet to write or queue */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_short_put Put 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_asix_write(VOID *asix_class, NX_PACKET *packet) +{ + +UX_TRANSFER *transfer_request; +UINT status; +NX_PACKET *current_packet; +NX_PACKET *next_packet; +UCHAR *packet_header; +UX_HOST_CLASS_ASIX *asix; + + /* Proper class casting. */ + asix = (UX_HOST_CLASS_ASIX *) asix_class; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_ASIX_WRITE, asix, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (asix -> ux_host_class_asix_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, asix, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Load the address of the current packet header at the physical header. */ + packet_header = packet -> nx_packet_prepend_ptr; + + /* Substract 2 USHORT to store length of the packet. */ + packet_header -= sizeof(USHORT) * 2; + +#if defined(UX_HOST_CLASS_ASIX_HEADER_CHECK_ENABLE) + /* Check packet compatibility to avoid writing to unexpected area. */ + if (packet_header < packet -> nx_packet_data_start) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEMORY_ERROR); + return(UX_HOST_CLASS_MEMORY_ERROR); + } +#endif + + /* Store the length of the payload in the first USHORT. */ + _ux_utility_short_put(packet_header, (USHORT)(packet -> nx_packet_length)); + + /* Store the negative length of the payload in the first USHORT. */ + _ux_utility_short_put(packet_header + sizeof(USHORT), (USHORT)(~packet -> nx_packet_length)); + + /* Check the queue. See if there is something that is being sent. */ + if (asix -> ux_host_class_asix_xmit_queue == UX_NULL) + { + + /* Nothing is in the queue. We need to arm this transfer. */ + /* Get the pointer to the bulk out endpoint transfer request. */ + transfer_request = &asix -> ux_host_class_asix_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Setup the transaction parameters. */ + transfer_request -> ux_transfer_request_data_pointer = packet_header; + transfer_request -> ux_transfer_request_requested_length = packet -> nx_packet_length + (ULONG)sizeof(USHORT) * 2; + + /* Store the packet that owns this transaction. */ + transfer_request -> ux_transfer_request_user_specific = packet; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check if the transaction was armed successfully. We do not wait for the packet to be sent here. */ + if (status == UX_SUCCESS) + { + + /* Memorize this packet at the beginning of the queue. */ + asix -> ux_host_class_asix_xmit_queue = packet; + + /* Reset the queue pointer of this packet. */ + packet -> nx_packet_queue_next = UX_NULL; + + } + + else + + /* Could not arm this transfer. */ + return(UX_ERROR); + + } + + else + + { + + /* We get here when there is something in the queue. */ + current_packet = asix -> ux_host_class_asix_xmit_queue; + + /* Get the next packet associated with the first packet. */ + next_packet = current_packet -> nx_packet_queue_next; + + /* Parse the current chain for the end. */ + while (next_packet != NX_NULL) + { + /* Remember the current packet. */ + current_packet = next_packet; + + /* See what the next packet in the chain is. */ + next_packet = current_packet -> nx_packet_queue_next; + } + + /* Memorize the packet to be sent. */ + current_packet -> nx_packet_queue_next = packet; + + /* The packet to be sent is the last in the chain. */ + packet -> nx_packet_queue_next = NX_NULL; + + } + + /* We are done here. */ + return(UX_SUCCESS); + +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_activate.c b/common/usbx_host_classes/src/ux_host_class_audio_activate.c new file mode 100644 index 0000000..c6bafac --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_activate.c @@ -0,0 +1,209 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function activates the audio class. It may be called twice by */ +/* the same device if there is a audio control interface to this */ +/* device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_audio_configure Configure the audio class */ +/* _ux_host_class_audio_descriptor_get Get audio descriptor */ +/* _ux_host_class_audio_device_controls_list_get Get controls list */ +/* _ux_host_class_audio_device_type_get Get device type */ +/* _ux_host_class_audio_streaming_terminal_get Get streaming terminal */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy class instance */ +/* _ux_utility_memory_allocate Allocate a memory block */ +/* _ux_utility_semaphore_create Create protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_INTERFACE *interface; +UX_HOST_CLASS_AUDIO *audio; +UINT status; + + + /* The audio is always activated by the interface descriptor and not the + device descriptor. */ + interface = (UX_INTERFACE *) command -> ux_host_class_command_container; + + /* Check the subclass of the new device. If it is a Audio Control Interface, + we don't need to create an instance of this function. When we get the streaming interface, + we will search the audio control interface for the device. */ + if (interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_AUDIO_SUBCLASS_CONTROL) + return(UX_SUCCESS); + + /* Obtain memory for this class instance. */ + audio = (UX_HOST_CLASS_AUDIO *) _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS_AUDIO)); + if (audio == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance. */ + audio -> ux_host_class_audio_class = command -> ux_host_class_command_class_ptr; + + /* Store the interface container into the audio class instance. */ + audio -> ux_host_class_audio_streaming_interface = interface; + + /* Store the device container into the audio class instance. */ + audio -> ux_host_class_audio_device = interface -> ux_interface_configuration -> ux_configuration_device; + + /* This instance of the device must also be stored in the interface container. */ + interface -> ux_interface_class_instance = (VOID *) audio; + + /* This instance of the device must also be stored in the interface container. */ + interface -> ux_interface_class_instance = (VOID *) audio; + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(audio -> ux_host_class_audio_class, (VOID *) audio); + + /* Configure the audio. */ + status = _ux_host_class_audio_configure(audio); + if (status != UX_SUCCESS) + { + + /* Error, destroy the class instance. */ + _ux_host_stack_class_instance_destroy(audio -> ux_host_class_audio_class, (VOID *) audio); + + /* Return the error. */ + return(status); + } + + /* Get the audio descriptor (all the class specific stuff) and memorize them + as we will need these descriptors to change settings. */ + status = _ux_host_class_audio_descriptor_get(audio); + if (status != UX_SUCCESS) + { + + /* Error, destroy the class instance. */ + _ux_host_stack_class_instance_destroy(audio -> ux_host_class_audio_class, (VOID *) audio); + + /* Return the error. */ + return(status); + } + + /* Locate the audio device streaming terminal. */ + status = _ux_host_class_audio_streaming_terminal_get(audio); + if (status != UX_SUCCESS) + { + + /* Error, destroy the class instance. */ + _ux_host_stack_class_instance_destroy(audio -> ux_host_class_audio_class, (VOID *) audio); + + /* Return the error. */ + return(status); + } + + /* Get the audio device type. Here we only support input and output devices. */ + status = _ux_host_class_audio_device_type_get(audio); + if (status != UX_SUCCESS) + { + + /* Error, destroy the class instance. */ + _ux_host_stack_class_instance_destroy(audio -> ux_host_class_audio_class, (VOID *) audio); + + /* Return the error. */ + return(status); + } + + /* Get the audio device controls. */ + status = _ux_host_class_audio_device_controls_list_get(audio); + if (status != UX_SUCCESS) + { + + /* Error, destroy the class instance. */ + _ux_host_stack_class_instance_destroy(audio -> ux_host_class_audio_class, (VOID *) audio); + + /* Return the error. */ + return(status); + } + + /* Create the semaphore to protect multiple threads from accessing the same + audio instance. */ + status = _ux_utility_semaphore_create(&audio -> ux_host_class_audio_semaphore, "ux_hot_class_audio_semaphore", 1); + if (status != UX_SUCCESS) + return(UX_SEMAPHORE_ERROR); + + /* Mark the audio as live now. */ + audio -> ux_host_class_audio_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if ((status == UX_SUCCESS) && (_ux_system_host -> ux_system_host_change_function != UX_NULL)) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, audio -> ux_host_class_audio_class, (VOID *) audio); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_AUDIO_ACTIVATE, audio, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, audio, 0, 0, 0) + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_alternate_setting_locate.c b/common/usbx_host_classes/src/ux_host_class_audio_alternate_setting_locate.c new file mode 100644 index 0000000..3712513 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_alternate_setting_locate.c @@ -0,0 +1,244 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_alternate_setting_locate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function finds the right alternate setting according to the */ +/* sampling desired. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* audio_sampling Pointer to audio sampling */ +/* alternate_setting Pointer to located alternate */ +/* setting */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_alternate_setting_locate(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_SAMPLING *audio_sampling, + UINT *alternate_setting) +{ + +UCHAR * descriptor; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR audio_interface_descriptor; +ULONG total_descriptor_length; +UINT descriptor_length; +UINT descriptor_type; +UINT descriptor_subtype; +UINT interface_found; +ULONG lower_frequency; +ULONG higher_frequency; +UINT specific_frequency_count; + + + /* Get the descriptor to the entire configuration. */ + descriptor = audio -> ux_host_class_audio_configuration_descriptor; + total_descriptor_length = audio -> ux_host_class_audio_configuration_descriptor_length; + + /* Default is Interface descriptor not yet found. */ + interface_found = UX_FALSE; + + /* Scan the descriptor for the Audio Streaming interface. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + /* Process relative to descriptor type. */ + switch (descriptor_type) + { + + + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &interface_descriptor); + + /* Ensure we have the correct interface for Audio streaming. */ + if ((interface_descriptor.bInterfaceClass == UX_HOST_CLASS_AUDIO_CLASS) && + (interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_AUDIO_SUBCLASS_STREAMING)) + { + + /* Mark we have found it. */ + interface_found = UX_TRUE; + + /* And memorize the alternate setting. */ + *alternate_setting = interface_descriptor.bAlternateSetting; + } + else + { + + /* Haven't found it. */ + interface_found = UX_FALSE; + } + break; + + + case UX_HOST_CLASS_AUDIO_CS_INTERFACE: + + /* First make sure we have found the correct generic interface descriptor. */ + if ((interface_found == UX_TRUE) && (descriptor_subtype == UX_HOST_CLASS_AUDIO_CS_FORMAT_TYPE)) + { + + /* Parse the FORMAT_TYPE descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_audio_interface_descriptor_structure, + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &audio_interface_descriptor); + + /* This descriptor must refer to a PCM audio type. */ + if (audio_interface_descriptor.bFormatType != UX_HOST_CLASS_AUDIO_FORMAT_TYPE_I) + break; + + /* The number of channels demanded by the application must match. */ + if (audio_sampling -> ux_host_class_audio_sampling_channels != audio_interface_descriptor.bNrChannels) + break; + + /* The resolution demanded by the application must match. */ + if (audio_sampling -> ux_host_class_audio_sampling_resolution != audio_interface_descriptor.bBitResolution) + break; + + /* Check the frequency demanded. The descriptor frequency is either defined + as a min and max frequency or an array of specified values. */ + if (audio_interface_descriptor.bSamFreqType == 0) + { + + /* The declaration of frequency is contiguous, so get the minimum and maximum */ + lower_frequency = (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 1)) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 2)) << 16; + + higher_frequency = (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 3) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 4)) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 5)) << 16; + + /* Now compare with what is required. */ + if ((audio_sampling -> ux_host_class_audio_sampling_frequency >= lower_frequency) && + (audio_sampling -> ux_host_class_audio_sampling_frequency <= higher_frequency)) + { + + /* We have found the right alternate setting. */ + return(UX_SUCCESS); + } + } + else + { + + /* The declaration of the frequency is declared as an array of specific values. */ + for (specific_frequency_count = 0; specific_frequency_count < audio_interface_descriptor.bSamFreqType; + specific_frequency_count++) + { + + lower_frequency = (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + (specific_frequency_count * 3)) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 1 + (specific_frequency_count * 3))) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 2 + (specific_frequency_count * 3))) << 16; + + /* Now compare with what is required. */ + if (audio_sampling -> ux_host_class_audio_sampling_frequency == lower_frequency) + { + + /* We have found the right alternate setting. */ + return(UX_SUCCESS); + } + } + } + } + break; + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_NO_ALTERNATE_SETTING, audio, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We get here when either the report descriptor has a problem or we could + not find the right audio device. */ + return(UX_NO_ALTERNATE_SETTING); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_configure.c b/common/usbx_host_classes/src/ux_host_class_audio_configure.c new file mode 100644 index 0000000..c78b876 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_configure.c @@ -0,0 +1,174 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to */ +/* the device. Once the device is configured, its interface(s) will */ +/* be activated. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get Get interface */ +/* _ux_host_stack_device_configuration_get Get configuration */ +/* _ux_host_stack_device_configuration_select Select configuration */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_configure(UX_HOST_CLASS_AUDIO *audio) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_INTERFACE *interface; +UX_DEVICE *parent_device; +ULONG interface_number; + + + /* If the device has been configured already, we don't need to do it + again. */ + if (audio -> ux_host_class_audio_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* An audio device normally has one configuration. So retrieve the 1st configuration + only. */ + status = _ux_host_stack_device_configuration_get(audio -> ux_host_class_audio_device, 0, &configuration); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, audio -> ux_host_class_audio_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + + } + /* Check the audio power source and check the parent power source for + incompatible connections. */ + if (audio -> ux_host_class_audio_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* Get parent device. */ + parent_device = audio -> ux_host_class_audio_device -> ux_device_parent; + + /* If the device is NULL, the parent is the root audio and we don't have to worry + if the parent is not the root audio, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, audio, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration */ + status = _ux_host_stack_device_configuration_select(configuration); + + /* Start with interface number 0. */ + interface_number = 0; + + /* We only need to retrieve the audio streaming interface. */ + do + { + + /* Pickup interface. */ + status = _ux_host_stack_configuration_interface_get(configuration, (UINT) interface_number, 0, &interface); + + /* Check completion status. */ + if (status == UX_SUCCESS) + { + + /* Check the type of interface we have found - is it streaming? */ + if (interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_AUDIO_SUBCLASS_STREAMING) + { + + audio -> ux_host_class_audio_streaming_interface = interface; + audio -> ux_host_class_audio_streaming_interface -> ux_interface_class_instance = (VOID *)audio; + break; + } + } + } while(status == UX_SUCCESS); + + /* After we have parsed the audio interfaces, ensure the streaming interfaces is resent. */ + if (audio -> ux_host_class_audio_streaming_interface == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_INTERFACE_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_INTERFACE_HANDLE_UNKNOWN, interface, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We get here when we could not locate the interface(s) handle */ + return(UX_INTERFACE_HANDLE_UNKNOWN); + } + else + { + + return(UX_SUCCESS); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_control_get.c b/common/usbx_host_classes/src/ux_host_class_audio_control_get.c new file mode 100644 index 0000000..f8f625a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_control_get.c @@ -0,0 +1,212 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_control_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the static values for a single audio control */ +/* on either the master channel or a specific channel. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* audio_control Pointer to audio control */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_short_get Read 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_control_get(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_CONTROL *audio_control) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +UCHAR * control_buffer; + + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_audio_name, (VOID *) audio) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, audio, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &audio -> ux_host_class_audio_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the control buffer. */ + control_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 2); + if (control_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return an error. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + + /* Something went wrong. */ + return(status); + + /* Create a transfer request for the GET_MIN request. */ + transfer_request -> ux_transfer_request_data_pointer = control_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_AUDIO_GET_MIN; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = audio_control -> ux_host_class_audio_control_channel | (audio_control -> ux_host_class_audio_control << 8); + transfer_request -> ux_transfer_request_index = audio -> ux_host_class_audio_control_interface_number | (audio -> ux_host_class_audio_feature_unit_id << 8); + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire control buffer returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 2)) + { + + /* Update the MIN static value for the caller. */ + audio_control -> ux_host_class_audio_control_min = _ux_utility_short_get(control_buffer); + } + else + { + + /* Free the previous control buffer. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + } + + /* Create a transfer request for the GET_MAX request. */ + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_AUDIO_GET_MAX; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire control buffer returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 2)) + { + + /* Update the MAX static value for the caller. */ + audio_control -> ux_host_class_audio_control_max = _ux_utility_short_get(control_buffer); + } + else + { + + /* Free the previous control buffer. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + } + + /* Create a transfer request for the GET_RES request. */ + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_AUDIO_GET_RES; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire control buffer returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 2)) + { + + /* Update the RES static value for the caller. */ + audio_control -> ux_host_class_audio_control_res = _ux_utility_short_get(control_buffer); + } + + /* Free all used resources. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_control_value_get.c b/common/usbx_host_classes/src/ux_host_class_audio_control_value_get.c new file mode 100644 index 0000000..1d402bc --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_control_value_get.c @@ -0,0 +1,149 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_control_value_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the dynamic values for a single audio control */ +/* on either the master channel or a specific channel. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* audio_control Pointer to audio control */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_short_get Read 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_control_value_get(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_CONTROL *audio_control) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +UCHAR * control_buffer; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_AUDIO_CONTROL_VALUE_GET, audio, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_audio_name, (VOID *) audio) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, audio, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &audio -> ux_host_class_audio_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the control_buffer. */ + control_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 2); + if (control_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return error. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Create a transfer request for the GET_CUR_buffer request. */ + transfer_request -> ux_transfer_request_data_pointer = control_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_AUDIO_GET_CUR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = audio_control -> ux_host_class_audio_control_channel | (audio_control -> ux_host_class_audio_control << 8); + transfer_request -> ux_transfer_request_index = audio -> ux_host_class_audio_control_interface_number | (audio -> ux_host_class_audio_feature_unit_id << 8); + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire control buffer returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 2)) + { + + /* Update the CUR static value for the caller. */ + audio_control -> ux_host_class_audio_control_cur = _ux_utility_short_get(control_buffer); + } + + /* Free all used resources. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_control_value_set.c b/common/usbx_host_classes/src/ux_host_class_audio_control_value_set.c new file mode 100644 index 0000000..65f0b4e --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_control_value_set.c @@ -0,0 +1,154 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_control_value_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function updates the dynamic values for a single audio control */ +/* on either the master channel or a specific channel. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* audio_control Pointer to audio control */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_short_put Write 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_control_value_set(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_CONTROL *audio_control) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +UCHAR * control_buffer; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_AUDIO_CONTROL_VALUE_SET, audio, audio_control, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_audio_name, (VOID *) audio) != UX_SUCCESS) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, audio, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &audio -> ux_host_class_audio_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the control buffer. */ + control_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 2); + if (control_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return an error. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Update the control buffer with the current control value. */ + _ux_utility_short_put(control_buffer, (USHORT) audio_control -> ux_host_class_audio_control_cur); + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + + /* Something went wrong. */ + return(status); + + /* Create a transfer request for the SET_CUR_buffer request. */ + transfer_request -> ux_transfer_request_data_pointer = control_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_AUDIO_SET_CUR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = audio_control -> ux_host_class_audio_control_channel | (audio_control -> ux_host_class_audio_control << 8); + transfer_request -> ux_transfer_request_index = audio -> ux_host_class_audio_control_interface_number | (audio -> ux_host_class_audio_feature_unit_id << 8); + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Free all used resources. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_deactivate.c b/common/usbx_host_classes/src/ux_host_class_audio_deactivate.c new file mode 100644 index 0000000..0d7f192 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_deactivate.c @@ -0,0 +1,129 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the audio has been */ +/* removed from the bus either directly or indirectly. The iso pipes */ +/* will be destroyed and the instanced removed. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy class instance */ +/* _ux_host_stack_endpoint_transfer_abort Abort outstanding transfer */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_AUDIO *audio; +UINT status; + + /* Get the instance for this class. */ + audio= (UX_HOST_CLASS_AUDIO *) command -> ux_host_class_command_instance; + + /* The audio is being shut down. */ + audio -> ux_host_class_audio_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* We need to abort transactions on the iso out pipe. */ + _ux_host_stack_endpoint_transfer_abort(audio -> ux_host_class_audio_isochronous_endpoint); + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(audio -> ux_host_class_audio_class, (VOID *) audio); + + /* Destroy the semaphore. */ + _ux_utility_semaphore_delete(&audio -> ux_host_class_audio_semaphore); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, audio -> ux_host_class_audio_class, (VOID *) audio); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_AUDIO_DEACTIVATE, audio, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(audio); + + /* Free the audio instance memory. */ + _ux_utility_memory_free(audio); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_descriptor_get.c b/common/usbx_host_classes/src/ux_host_class_audio_descriptor_get.c new file mode 100644 index 0000000..41d7332 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_descriptor_get.c @@ -0,0 +1,158 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_descriptor_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the entire audio configuration descriptors. */ +/* This is needed because the audio class has many class specific */ +/* descriptors which describe the alternate settings that can be used. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_descriptor_get(UX_HOST_CLASS_AUDIO *audio) +{ + +UCHAR * descriptor; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UX_CONFIGURATION configuration; +UINT status; +ULONG total_configuration_length; + + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &audio -> ux_host_class_audio_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the descriptor. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_CONFIGURATION_DESCRIPTOR_LENGTH); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Create a transfer request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = UX_CONFIGURATION_DESCRIPTOR_LENGTH; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_CONFIGURATION_DESCRIPTOR_ITEM << 8; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == UX_CONFIGURATION_DESCRIPTOR_LENGTH)) + { + + /* The descriptor is in a packed format, parse it locally. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, (UCHAR *) &configuration.ux_configuration_descriptor); + + /* Now we have the configuration descriptor which will tell us how many + bytes there are in the entire descriptor. */ + total_configuration_length = configuration.ux_configuration_descriptor.wTotalLength; + + /* Free the previous descriptor. */ + _ux_utility_memory_free(descriptor); + + /* Allocate enough memory to read all descriptors attached + to this configuration. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, total_configuration_length); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Set the length we need to retrieve. */ + transfer_request -> ux_transfer_request_requested_length = total_configuration_length; + + /* And reprogram the descriptor buffer address. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == total_configuration_length)) + { + + /* Save the address of the entire configuration descriptor of the audio device. */ + audio -> ux_host_class_audio_configuration_descriptor = descriptor; + + /* Save the length of the entire descriptor too. */ + audio -> ux_host_class_audio_configuration_descriptor_length = total_configuration_length; + + /* We do not free the resource for the descriptor until the device is + plugged out. */ + return(UX_SUCCESS); + } + } + + /* Free all used resources. */ + _ux_utility_memory_free(descriptor); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_device_controls_list_get.c b/common/usbx_host_classes/src/ux_host_class_audio_device_controls_list_get.c new file mode 100644 index 0000000..efaf0db --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_device_controls_list_get.c @@ -0,0 +1,253 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_device_controls_list_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the controls for the audio device. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_utility_long_get Get 32-bit word */ +/* _ux_utility_short_get Get 16-bit word */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_device_controls_list_get(UX_HOST_CLASS_AUDIO *audio) +{ + +UCHAR * descriptor; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UX_HOST_CLASS_AUDIO_INPUT_TERMINAL_DESCRIPTOR input_interface_descriptor; +UX_HOST_CLASS_AUDIO_FEATURE_UNIT_DESCRIPTOR feature_unit_interface_descriptor; +ULONG total_descriptor_length; +ULONG descriptor_length; +ULONG descriptor_type; +ULONG descriptor_subtype; +ULONG descriptor_found; +ULONG control_size_bytes; +UCHAR * control_bit_map_address; +ULONG channel_number; + + + /* Get the descriptor to the entire configuration */ + descriptor = audio -> ux_host_class_audio_configuration_descriptor; + total_descriptor_length = audio -> ux_host_class_audio_configuration_descriptor_length; + + /* Default is Interface descriptor not yet found. */ + descriptor_found = UX_FALSE; + + /* Scan the descriptor for the Audio Streaming interface. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Process relative to descriptor type. */ + switch(descriptor_type) + { + + + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &interface_descriptor); + + /* Ensure we have the correct interface for Audio streaming. */ + if ((interface_descriptor.bInterfaceClass == UX_HOST_CLASS_AUDIO_CLASS) && + (interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_AUDIO_SUBCLASS_CONTROL)) + + /* Mark we have found it. */ + descriptor_found = UX_TRUE; + else + + descriptor_found = UX_FALSE; + break; + + + case UX_HOST_CLASS_AUDIO_CS_INTERFACE: + + /* First make sure we have found the correct generic interface descriptor. */ + if (descriptor_found == UX_TRUE) + { + + /* Check the sub type. */ + switch (descriptor_subtype) + { + + case UX_HOST_CLASS_AUDIO_CS_INPUT_TERMINAL: + + /* Make the descriptor machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_audio_input_terminal_descriptor_structure, + UX_HOST_CLASS_AUDIO_INPUT_TERMINAL_DESCRIPTOR_ENTRIES, (UCHAR *) &input_interface_descriptor); + + /* Get the number of channels and check for maximum allowed. */ + if (input_interface_descriptor.bNrChannels > UX_HOST_CLASS_AUDIO_MAX_CHANNEL) + audio -> ux_host_class_audio_channels = UX_HOST_CLASS_AUDIO_MAX_CHANNEL; + else + audio -> ux_host_class_audio_channels = input_interface_descriptor.bNrChannels; + break; + + + case UX_HOST_CLASS_AUDIO_CS_FEATURE_UNIT: + + /* Make the descriptor machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_audio_feature_unit_descriptor_structure, + UX_HOST_CLASS_AUDIO_FEATURE_UNIT_DESCRIPTOR_ENTRIES, (UCHAR *) &feature_unit_interface_descriptor); + + /* Store the Feature Unit ID, used to set/get the audio controls. */ + audio -> ux_host_class_audio_feature_unit_id = feature_unit_interface_descriptor.bUnitID; + + /* Get the size of each control in bytes. */ + control_size_bytes = feature_unit_interface_descriptor.bControlSize; + + /* Get the address of the first control bit map. */ + control_bit_map_address = (UCHAR *) &feature_unit_interface_descriptor.bmaControls; + + /* Walk all the controls and retrieve them one by one. */ + for (channel_number = 0; channel_number < audio -> ux_host_class_audio_channels; channel_number++) + { + + /* Each control has the same size. */ + switch (control_size_bytes) + { + + case 1: + + /* Byte aligned control. */ + audio -> ux_host_class_audio_channel_control[channel_number] = (ULONG) *control_bit_map_address; + break; + + + case 2: + + /* Word aligned control. */ + audio -> ux_host_class_audio_channel_control[channel_number] = (ULONG) _ux_utility_short_get(control_bit_map_address); + break; + + + case 4: + + /* Long aligned control. */ + audio -> ux_host_class_audio_channel_control[channel_number] = _ux_utility_long_get(control_bit_map_address); + break; + + + default: + + /* Not sure what we should do here, we ignore the control. */ + break; + } + + /* Point to the next control. */ + control_bit_map_address += control_size_bytes; + } + + /* Return successful completion. */ + return(UX_SUCCESS); + } + } + break; + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_AUDIO_WRONG_TYPE); + + /* We get here when either the report descriptor has a problem or we could + not find the right audio device. */ + return(UX_HOST_CLASS_AUDIO_WRONG_TYPE); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_device_type_get.c b/common/usbx_host_classes/src/ux_host_class_audio_device_type_get.c new file mode 100644 index 0000000..36e1365 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_device_type_get.c @@ -0,0 +1,220 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_device_type_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the device type. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_device_type_get(UX_HOST_CLASS_AUDIO *audio) +{ + +UCHAR * descriptor; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UX_HOST_CLASS_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR output_interface_descriptor; +UX_HOST_CLASS_AUDIO_INPUT_TERMINAL_DESCRIPTOR input_interface_descriptor; +ULONG total_descriptor_length; +ULONG descriptor_length; +ULONG descriptor_type; +ULONG descriptor_subtype; +ULONG descriptor_found; + + + /* Get the descriptor to the entire configuration. */ + descriptor = audio -> ux_host_class_audio_configuration_descriptor; + total_descriptor_length = audio -> ux_host_class_audio_configuration_descriptor_length; + + /* Default is Interface descriptor not yet found. */ + descriptor_found = UX_FALSE; + + /* Scan the descriptor for the Audio Streaming interface. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Process relative to the descriptor type. */ + switch (descriptor_type) + { + + + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &interface_descriptor); + + /* Ensure we have the correct interface for Audio Control. */ + if ((interface_descriptor.bInterfaceClass == UX_HOST_CLASS_AUDIO_CLASS) && + (interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_AUDIO_SUBCLASS_CONTROL)) + { + + /* Mark we have found it. */ + descriptor_found = UX_TRUE; + + /* Get the interface number of this descriptor and save it in the audio + instance. This will be useful to program the audio controls. */ + audio -> ux_host_class_audio_control_interface_number = interface_descriptor.bInterfaceNumber; + } + else + { + + descriptor_found = UX_FALSE; + } + break; + + + case UX_HOST_CLASS_AUDIO_CS_INTERFACE: + + /* First make sure we have found the correct generic interface descriptor. */ + if (descriptor_found == UX_TRUE) + { + + /* Check the sub type. */ + switch (descriptor_subtype) + { + + + case UX_HOST_CLASS_AUDIO_CS_INPUT_TERMINAL: + + /* Make the descriptor machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_audio_input_terminal_descriptor_structure, + UX_HOST_CLASS_AUDIO_INPUT_TERMINAL_DESCRIPTOR_ENTRIES, (UCHAR *) &input_interface_descriptor); + + /* Make sure we have the right terminal link. */ + if (input_interface_descriptor.bTerminalID == audio -> ux_host_class_audio_terminal_link) + { + + audio -> ux_host_class_audio_type = UX_HOST_CLASS_AUDIO_OUTPUT; + + /* Return successful completion. */ + return(UX_SUCCESS); + } + + break; + + case UX_HOST_CLASS_AUDIO_CS_OUTPUT_TERMINAL: + + /* Make the descriptor machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_audio_output_terminal_descriptor_structure, + UX_HOST_CLASS_AUDIO_OUTPUT_TERMINAL_DESCRIPTOR_ENTRIES, (UCHAR *) &output_interface_descriptor); + + /* Make sure we have the right terminal link. */ + if (output_interface_descriptor.bTerminalID == audio -> ux_host_class_audio_terminal_link) + { + + audio -> ux_host_class_audio_type = UX_HOST_CLASS_AUDIO_INPUT; + + /* Return successful completion. */ + return(UX_SUCCESS); + } + } + } + break; + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_AUDIO_WRONG_TYPE); + + /* We get here when either the report descriptor has a problem or we could + not find the right audio device. */ + return(UX_HOST_CLASS_AUDIO_WRONG_TYPE); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_audio_endpoints_get.c new file mode 100644 index 0000000..e566d59 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_endpoints_get.c @@ -0,0 +1,118 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function searches for the handle of the isochronous endpoints. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_endpoints_get(UX_HOST_CLASS_AUDIO *audio) +{ + +UINT status; +UINT endpoint_index; +UX_ENDPOINT *endpoint; + + + /* Search the ISO OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < audio -> ux_host_class_audio_streaming_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get interface endpoint. */ + status = _ux_host_stack_interface_endpoint_get(audio -> ux_host_class_audio_streaming_interface, endpoint_index, &endpoint); + + /* Check completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is iso and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_ISOCHRONOUS_ENDPOINT)) + { + + /* We have found the bulk endpoint, save it. */ + audio -> ux_host_class_audio_isochronous_endpoint = endpoint; + break; + } + } + } + + /* The isochronous endpoint is mandatory. If we didn't find it, return an error. */ + if (audio -> ux_host_class_audio_isochronous_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, audio, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_entry.c b/common/usbx_host_classes/src/ux_host_class_audio_entry.c new file mode 100644 index 0000000..528b74d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_entry.c @@ -0,0 +1,128 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the Audio class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* audio device (speaker, microphone ...) on the bus or when the audio */ +/* device is removed. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_audio_activate Activate audio class */ +/* _ux_host_class_audio_deactivate Deactivate audio class */ +/* */ +/* CALLED BY */ +/* */ +/* Host Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if ((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) && + (command -> ux_host_class_command_class == UX_HOST_CLASS_AUDIO_CLASS)) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_audio_activate(command); + + /* Return completion status. */ + return(status); + + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_audio_deactivate(command); + + /* Return completion status. */ + return(status); + + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_read.c b/common/usbx_host_classes/src/ux_host_class_audio_read.c new file mode 100644 index 0000000..e145970 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_read.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the audio streaming interface. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* audio_transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_audio_transfer_request Audio transfer request */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Put semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_read(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST *audio_transfer_request) +{ + +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_AUDIO_READ, audio, audio_transfer_request -> ux_host_class_audio_transfer_request_data_pointer, + audio_transfer_request -> ux_host_class_audio_transfer_request_requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_audio_name, (VOID *) audio) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, audio, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* By default the transmission will be successful. */ + status = UX_SUCCESS; + + /* Ensure we have a selected interface that allows isoch transmission. */ + if (audio -> ux_host_class_audio_isochronous_endpoint -> ux_endpoint_descriptor.wMaxPacketSize == 0) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_AUDIO_WRONG_INTERFACE); + + /* Return error status. */ + return(UX_HOST_CLASS_AUDIO_WRONG_INTERFACE); + } + + /* Hook the audio transfer request to the chain of transfer requests in the audio instance. */ + audio_transfer_request -> ux_host_class_audio_transfer_request_next_audio_transfer_request = audio -> ux_host_class_audio_tail_transfer_request; + audio -> ux_host_class_audio_tail_transfer_request = audio_transfer_request; + + /* Check if this is the first time we have had a transfer request, if so update the head as well. */ + if (audio -> ux_host_class_audio_head_transfer_request == UX_NULL) + audio -> ux_host_class_audio_head_transfer_request = audio_transfer_request; + + /* For audio in, we read packets at a time, so the transfer request size is the size of the + endpoint. */ + audio_transfer_request -> ux_host_class_audio_transfer_request_requested_length = + audio -> ux_host_class_audio_isochronous_endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + + /* Ask the stack to hook this transfer request to the iso ED. */ + status = _ux_host_class_audio_transfer_request(audio, audio_transfer_request); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_get.c b/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_get.c new file mode 100644 index 0000000..2a9b040 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_get.c @@ -0,0 +1,395 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_streaming_sampling_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains successive sampling characteristics for the */ +/* audio streaming channel. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* audio_sampling Pointer to audio sampling */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_utility_descriptor_parse Parse the descriptor */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Put semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_streaming_sampling_get(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_SAMPLING_CHARACTERISTICS *audio_sampling) +{ + +UINT status; +UCHAR * descriptor; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR audio_interface_descriptor; +ULONG total_descriptor_length; +UINT descriptor_length; +UINT descriptor_type; +UINT descriptor_subtype; +UINT interface_found; +ULONG lower_frequency; +ULONG higher_frequency; +UINT specific_frequency_count; +UINT previous_match_found; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_AUDIO_STREAMING_SAMPLING_GET, audio, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_audio_name, (VOID *) audio) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, audio, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* Reset the match flag. */ + previous_match_found = UX_FALSE; + + /* Get the descriptor to the entire configuration. */ + descriptor = audio -> ux_host_class_audio_configuration_descriptor; + total_descriptor_length = audio -> ux_host_class_audio_configuration_descriptor_length; + + /* Default is Interface descriptor not yet found. */ + interface_found = UX_FALSE; + + /* Scan the descriptor for the Audio Streaming interface. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Process relative to descriptor type. */ + switch(descriptor_type) + { + + + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Parse the interface descriptor and make it machine independent */ + _ux_utility_descriptor_parse(descriptor, _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &interface_descriptor); + + /* Ensure we have the correct interface for Audio streaming. */ + if ((interface_descriptor.bInterfaceClass == UX_HOST_CLASS_AUDIO_CLASS) && + (interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_AUDIO_SUBCLASS_STREAMING)) + { + + /* Mark we have found it. */ + interface_found = UX_TRUE; + } + else + { + interface_found = UX_FALSE; + } + break; + + + case UX_HOST_CLASS_AUDIO_CS_INTERFACE: + + /* First make sure we have found the correct generic interface descriptor. */ + if ((interface_found == UX_TRUE) && (descriptor_subtype == UX_HOST_CLASS_AUDIO_CS_FORMAT_TYPE)) + { + + /* Parse the FORMAT_TYPE descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_audio_interface_descriptor_structure, + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &audio_interface_descriptor); + + /* This descriptor must refer to a PCM audio type. */ + if (audio_interface_descriptor.bFormatType != UX_HOST_CLASS_AUDIO_FORMAT_TYPE_I) + break; + + /* If this is the first time we ask for a streaming interface characteristics + we return the first we find. */ + if ((audio_sampling -> ux_host_class_audio_sampling_characteristics_channels == 0) && + (audio_sampling -> ux_host_class_audio_sampling_characteristics_resolution == 0)) + { + + audio_sampling -> ux_host_class_audio_sampling_characteristics_channels = audio_interface_descriptor.bNrChannels; + audio_sampling -> ux_host_class_audio_sampling_characteristics_resolution = audio_interface_descriptor.bBitResolution; + + if (audio_interface_descriptor.bSamFreqType == 0) + { + + /* The declaration of frequency is contiguous, so get the minimum and maximum */ + audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_low = + (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 1)) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 2)) << 16; + + audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_high = + (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 3) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 4)) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 5)) << 16; + } + else + { + + /* The declaration of the frequency is declared as an array of specific values. + We take the first one here. */ + audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_low = + (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH ) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 1 )) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 2 )) << 16; + + /* High and low frequencies are the same here. */ + audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_high = audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_low; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* We have found the first streaming characteristics. */ + return(UX_SUCCESS); + } + } + else + { + + /* This is not the second time we ask for the characteristics, we need + to find 1st where we left off and look at the next characteristics. */ + if ((audio_sampling -> ux_host_class_audio_sampling_characteristics_channels == audio_interface_descriptor.bNrChannels) && + (audio_sampling -> ux_host_class_audio_sampling_characteristics_resolution == audio_interface_descriptor.bBitResolution)) + { + + if (audio_interface_descriptor.bSamFreqType == 0) + { + + /* The declaration of frequency is contiguous, so get the minimum and maximum. */ + lower_frequency = (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 1)) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 2)) << 16; + + higher_frequency = (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 3) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 4)) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 5)) << 16; + + if ((audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_low == lower_frequency) && + (audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_high == higher_frequency)) + { + + /* We have a match. */ + previous_match_found = UX_TRUE; + break; + } + } + else + { + + /* The declaration of the frequency is declared as an array of specific values. */ + for (specific_frequency_count = 0; specific_frequency_count < audio_interface_descriptor.bSamFreqType; specific_frequency_count++) + { + + lower_frequency = (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + (specific_frequency_count * 3)) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 1 + (specific_frequency_count * 3))) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 2 + (specific_frequency_count * 3))) << 16; + + /* Compare the frequency. */ + if (audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_low == lower_frequency) + { + + previous_match_found = UX_TRUE; + } + else + { + + /* Now the frequency is different, if we had a match before + this becomes the next characteristics found. */ + if (previous_match_found == UX_TRUE) + { + + /* We return this characteristics. */ + audio_sampling -> ux_host_class_audio_sampling_characteristics_channels = audio_interface_descriptor.bNrChannels; + audio_sampling -> ux_host_class_audio_sampling_characteristics_resolution = audio_interface_descriptor.bBitResolution; + audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_low = lower_frequency; + audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_high = lower_frequency; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return successful completion. */ + return(UX_SUCCESS); + } + } + } + } + } + else + { + + /* We come here when the current characteristics does not match + the one given by the application. We need to check if we had found a match + before in which case, this is the one we need to return. */ + if (previous_match_found == UX_TRUE) + { + + /* We return this characteristics. */ + audio_sampling -> ux_host_class_audio_sampling_characteristics_channels = audio_interface_descriptor.bNrChannels; + audio_sampling -> ux_host_class_audio_sampling_characteristics_resolution = audio_interface_descriptor.bBitResolution; + + if (audio_interface_descriptor.bSamFreqType == 0) + { + + /* The declaration of frequency is contiguous, so get the minimum and maximum. */ + lower_frequency = (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 1)) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 2)) << 16; + + higher_frequency = (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 3) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 4)) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 5)) << 16; + + audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_low = lower_frequency; + audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_high = higher_frequency; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return successful completion. */ + return(UX_SUCCESS); + } + else + { + + lower_frequency = (ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH) | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 1)) << 8 | + ((ULONG) *(descriptor + UX_HOST_CLASS_AUDIO_INTERFACE_DESCRIPTOR_LENGTH + 2)) << 16; + + audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_low = lower_frequency; + audio_sampling -> ux_host_class_audio_sampling_characteristics_frequency_high = lower_frequency; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return successful completion. */ + return(UX_SUCCESS); + } + } + } + } + } + } + + /* Verify the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_NO_ALTERNATE_SETTING); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_NO_ALTERNATE_SETTING, audio, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We get here when either the report descriptor has a problem or we could + not find the right audio device. */ + return(UX_NO_ALTERNATE_SETTING); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_set.c b/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_set.c new file mode 100644 index 0000000..a69a932 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_streaming_sampling_set.c @@ -0,0 +1,187 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_streaming_sampling_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function selects the right alternate setting for the audio */ +/* streaming interface based on the sampling values specified by the */ +/* user. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* audio_sampling Pointer to audio sampling */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_audio_alternate_setting_locate */ +/* Locate alternate setting */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* _ux_host_stack_interface_setting_select Select interface */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Put semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_streaming_sampling_set(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_SAMPLING *audio_sampling) +{ + +UINT status; +UINT alternate_setting; +ULONG endpoint_index; +UX_CONFIGURATION *configuration; +UX_INTERFACE *interface; +UX_ENDPOINT *endpoint; +UINT streaming_interface; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_AUDIO_STREAMING_SAMPLING_SET, audio, audio_sampling, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_audio_name, (VOID *) audio) != UX_SUCCESS) + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* Find the correct alternate setting for the sampling desired. */ + status = _ux_host_class_audio_alternate_setting_locate(audio, audio_sampling, &alternate_setting); + + /* Did we find the alternate setting? */ + if (status != UX_SUCCESS) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + return(status); + } + + /* We found the alternate setting for the sampling values demanded, now we need + to search its container. */ + configuration = audio -> ux_host_class_audio_streaming_interface -> ux_interface_configuration; + interface = configuration -> ux_configuration_first_interface; + streaming_interface = audio -> ux_host_class_audio_streaming_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Scan all interfaces. */ + while (interface != UX_NULL) + { + + /* We search for both the right interface and alternate setting. */ + if ((interface -> ux_interface_descriptor.bInterfaceNumber == streaming_interface) && + (interface -> ux_interface_descriptor.bAlternateSetting == alternate_setting)) + { + + /* We have found the right interface/alternate setting combination + The stack will select it for us. */ + status = _ux_host_stack_interface_setting_select(interface); + + /* If the alternate setting for the streaming interface could be selected, we memorize it. */ + if (status == UX_SUCCESS) + { + + /* Memorize the interface. */ + audio -> ux_host_class_audio_streaming_interface = interface; + + /* We need to research the isoch endpoint now. */ + for (endpoint_index = 0; endpoint_index < interface -> ux_interface_descriptor.bNumEndpoints; endpoint_index++) + { + + /* Get the list of endpoints one by one. */ + status = _ux_host_stack_interface_endpoint_get(audio -> ux_host_class_audio_streaming_interface, + endpoint_index, &endpoint); + + /* Check completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is ISOCH, regardless of the direction. */ + if ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_ISOCHRONOUS_ENDPOINT) + { + + /* We have found the isoch endpoint, save it. */ + audio -> ux_host_class_audio_isochronous_endpoint = endpoint; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return successful completion. */ + return(UX_SUCCESS); + } + } + } + } + } + + /* Move to next interface. */ + interface = interface -> ux_interface_next_interface; + } + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_NO_ALTERNATE_SETTING); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_NO_ALTERNATE_SETTING, audio, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We get here if we could not get the right alternate setting. */ + return(UX_NO_ALTERNATE_SETTING); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_streaming_terminal_get.c b/common/usbx_host_classes/src/ux_host_class_audio_streaming_terminal_get.c new file mode 100644 index 0000000..3146598 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_streaming_terminal_get.c @@ -0,0 +1,191 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_streaming_terminal_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function searches and retrieves the streaming terminal. This */ +/* terminal is used to further search which of the input\output */ +/* terminals describes if the device is audio IN or audio OUT. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_streaming_terminal_get(UX_HOST_CLASS_AUDIO *audio) +{ + +UCHAR * descriptor; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UX_HOST_CLASS_AUDIO_STREAMING_INTERFACE_DESCRIPTOR streaming_interface_descriptor; +ULONG total_descriptor_length; +ULONG descriptor_length; +ULONG descriptor_type; +ULONG descriptor_subtype; +ULONG descriptor_found; + + + /* Get the descriptor to the entire configuration */ + descriptor = audio -> ux_host_class_audio_configuration_descriptor; + total_descriptor_length = audio -> ux_host_class_audio_configuration_descriptor_length; + + /* Default is Interface descriptor not yet found. */ + descriptor_found = UX_FALSE; + audio -> ux_host_class_audio_terminal_link = 0xffffffff; + + /* Scan the descriptor for the Audio Streaming interface. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Process relative to the descriptor type. */ + switch(descriptor_type) + { + + + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &interface_descriptor); + + /* Ensure we have the correct interface for Audio streaming. */ + if ((interface_descriptor.bInterfaceClass == UX_HOST_CLASS_AUDIO_CLASS) && + (interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_AUDIO_SUBCLASS_STREAMING) && + (interface_descriptor.bInterfaceNumber == audio -> ux_host_class_audio_streaming_interface -> ux_interface_descriptor.bInterfaceNumber)) + + /* Mark we have found it. */ + descriptor_found = UX_TRUE; + else + + descriptor_found = UX_FALSE; + break; + + + case UX_HOST_CLASS_AUDIO_CS_INTERFACE: + + /* First make sure we have found the correct generic interface descriptor. */ + if (descriptor_found == UX_TRUE) + { + + /* Check the sub type. */ + switch(descriptor_subtype) + { + + + case UX_HOST_CLASS_AUDIO_CS_AS_GENERAL: + + /* Make the descriptor machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_audio_streaming_interface_descriptor_structure, + UX_HOST_CLASS_AUDIO_STREAMING_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &streaming_interface_descriptor); + + /* Save the terminal link. */ + audio -> ux_host_class_audio_terminal_link = streaming_interface_descriptor.bTerminalLink; + return(UX_SUCCESS); + } + } + break; + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_AUDIO_WRONG_TYPE); + + /* We get here when either the report descriptor has a problem or we could + not find the right audio device. */ + return(UX_HOST_CLASS_AUDIO_WRONG_TYPE); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_transfer_request.c b/common/usbx_host_classes/src/ux_host_class_audio_transfer_request.c new file mode 100644 index 0000000..5c441e2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_transfer_request.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_transfer_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function submits an isochronous audio transfer request to the */ +/* USBX stack. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* audio_transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_transfer_request(UX_HOST_CLASS_AUDIO *audio, + UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST *audio_transfer_request) +{ + +UINT status; +UX_TRANSFER *transfer_request; + + + /* The transfer request is embedded in the application transfer request. */ + transfer_request = &audio_transfer_request -> ux_host_class_audio_transfer_request; + + /* Select the direction. We do this by taking the endpoint direction. */ + transfer_request -> ux_transfer_request_type = audio -> ux_host_class_audio_isochronous_endpoint -> + ux_endpoint_descriptor.bEndpointAddress&UX_REQUEST_DIRECTION; + + /* Fill the transfer request with all the required fields. */ + transfer_request -> ux_transfer_request_endpoint = audio -> ux_host_class_audio_isochronous_endpoint; + transfer_request -> ux_transfer_request_data_pointer = audio_transfer_request -> ux_host_class_audio_transfer_request_data_pointer; + transfer_request -> ux_transfer_request_requested_length = audio_transfer_request -> ux_host_class_audio_transfer_request_requested_length; + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_audio_transfer_request_completed; + transfer_request -> ux_transfer_request_class_instance = audio; + + /* We memorize the application transfer request in the local transfer request. */ + transfer_request -> ux_transfer_request_user_specific = (VOID *) audio_transfer_request; + + /* Transfer the transfer request. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_transfer_request_completed.c b/common/usbx_host_classes/src/ux_host_class_audio_transfer_request_completed.c new file mode 100644 index 0000000..b71bf7a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_transfer_request_completed.c @@ -0,0 +1,96 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_transfer_request_completed PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives a completion call back on a isoch transfer */ +/* request. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_audio_transfer_request_completion_function) */ +/* Transfer request completion */ +/* */ +/* CALLED BY */ +/* */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_audio_transfer_request_completed(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST *audio_transfer_request; + + + /* Get the pointer to the audio specific transfer request, by nature of the lined transfer requests, + the corresponding transfer request has to be the head transfer request in the audio instance. */ + audio_transfer_request = (UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST *) transfer_request -> ux_transfer_request_user_specific; + + /* Do a sanity check on the transfer request, if NULL something is wrong. */ + if (audio_transfer_request == UX_NULL) + return; + + /* The caller's transfer request needs to be updated. */ + audio_transfer_request -> ux_host_class_audio_transfer_request_actual_length = transfer_request -> ux_transfer_request_actual_length; + audio_transfer_request -> ux_host_class_audio_transfer_request_completion_code = transfer_request -> ux_transfer_request_completion_code; + + /* Call the completion routine. */ + audio_transfer_request -> ux_host_class_audio_transfer_request_completion_function(audio_transfer_request); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_audio_write.c b/common/usbx_host_classes/src/ux_host_class_audio_write.c new file mode 100644 index 0000000..ef197c5 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_audio_write.c @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Audio Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_audio.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_audio_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the audio streaming interface. */ +/* */ +/* INPUT */ +/* */ +/* audio Pointer to audio class */ +/* audio_transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_audio_transfer_request Start audio transfer request */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Put semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Audio Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_audio_write(UX_HOST_CLASS_AUDIO *audio, UX_HOST_CLASS_AUDIO_TRANSFER_REQUEST *audio_transfer_request) +{ + +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_AUDIO_WRITE, audio, audio_transfer_request -> ux_host_class_audio_transfer_request_data_pointer, + audio_transfer_request -> ux_host_class_audio_transfer_request_requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_audio_name, (VOID *) audio) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, audio, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&audio -> ux_host_class_audio_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* By default the transmission will be successful. */ + status = UX_SUCCESS; + + /* Ensure we have a selected interface that allows isoch transmission. */ + if (audio -> ux_host_class_audio_isochronous_endpoint -> ux_endpoint_descriptor.wMaxPacketSize == 0) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_AUDIO_WRONG_INTERFACE); + + /* Return error status. */ + return(UX_HOST_CLASS_AUDIO_WRONG_INTERFACE); + } + + /* Hook the audio transfer request to the chain of transfer requests in the audio instance. + We hook the transfer request to the tail transfer request. */ + audio_transfer_request -> ux_host_class_audio_transfer_request_next_audio_transfer_request = audio -> ux_host_class_audio_tail_transfer_request; + audio -> ux_host_class_audio_tail_transfer_request = audio_transfer_request; + + /* Check if this is the first time we have a transfer request, if so update the head as well. */ + if (audio -> ux_host_class_audio_head_transfer_request == UX_NULL) + audio -> ux_host_class_audio_head_transfer_request = audio_transfer_request; + + /* Ask the stack to hook this transfer request to the iso ED. */ + status = _ux_host_class_audio_transfer_request(audio, audio_transfer_request); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&audio -> ux_host_class_audio_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_activate.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_activate.c new file mode 100644 index 0000000..add46c5 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_activate.c @@ -0,0 +1,242 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates the ACM instance, configure the device ... */ +/* */ +/* INPUT */ +/* */ +/* command ACM class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_cdc_acm_configure Configure cdc_acm class */ +/* _ux_host_class_cdc_acm_endpoints_get Get endpoints of cdc_acm */ +/* _ux_host_class_cdc_acm_ioctl IOCTL function for ACM */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_endpoint_transfer_abort Abort transfer */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_semaphore_create Create cdc_acm semaphore */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_utility_delay_ms Delay */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_cdc_acm_entry Entry of cdc_acm class */ +/* _ux_utility_delay_ms Delay ms */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_INTERFACE *interface; +UX_HOST_CLASS_CDC_ACM *cdc_acm; +UX_HOST_CLASS_CDC_ACM_LINE_CODING line_coding; +UX_HOST_CLASS_CDC_ACM_LINE_STATE line_state; +UINT status; + + /* The CDC ACM class is always activated by the interface descriptor and not the + device descriptor. */ + interface = (UX_INTERFACE *) command -> ux_host_class_command_container; + + /* Obtain memory for this class instance. */ + cdc_acm = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, sizeof(UX_HOST_CLASS_CDC_ACM)); + + /* Instance creation fail. */ + if (cdc_acm == UX_NULL) + + /* Memory allocation fail. */ + return(UX_MEMORY_INSUFFICIENT); + + /* Create the semaphore to protect 2 threads from accessing the same acm instance. */ + status = _ux_utility_semaphore_create(&cdc_acm -> ux_host_class_cdc_acm_semaphore, "ux_host_class_cdc_acm_semaphore", 1); + if (status != UX_SUCCESS) + { + + /* Free instance memory. */ + _ux_utility_memory_free(cdc_acm); + + /* Semaphore creation error. */ + return(UX_SEMAPHORE_ERROR); + } + + /* Store the class container into this instance. */ + cdc_acm -> ux_host_class_cdc_acm_class = command -> ux_host_class_command_class_ptr; + + /* Store the interface container into the cdc_acm class instance. */ + cdc_acm -> ux_host_class_cdc_acm_interface = interface; + + /* Store the device container into the cdc_acm class instance. */ + cdc_acm -> ux_host_class_cdc_acm_device = interface -> ux_interface_configuration -> ux_configuration_device; + + /* This instance of the device must also be stored in the interface container. */ + interface -> ux_interface_class_instance = (VOID *) cdc_acm; + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm); + + /* Configure the cdc_acm. */ + status = _ux_host_class_cdc_acm_configure(cdc_acm); + + /* If we are done success, go on to get endpoints. */ + if (status == UX_SUCCESS) + + /* Get the cdc_acm endpoint(s). Depending on the interface type, we will need to search for + Bulk Out and Bulk In endpoints and the optional interrupt endpoint. */ + status = _ux_host_class_cdc_acm_endpoints_get(cdc_acm); + + /* If we are done success, go on to mount interface. */ + if (status == UX_SUCCESS) + { + /* Mark the cdc_acm as mounting now. Both interfaces need to be mounting. */ + cdc_acm -> ux_host_class_cdc_acm_state = UX_HOST_CLASS_INSTANCE_MOUNTING; + + /* If we have the Control Class, we have to configure the speed, parity ... */ + if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS) + { + + /* We need to wait for some device to settle. The Radicom USB Modem is an example of + these device who fail the first Set_Line_Coding command if sent too quickly. + The timing does not have to be precise so we use the thread sleep function. + The default sleep value is 1 seconds. */ + _ux_utility_delay_ms(UX_HOST_CLASS_CDC_ACM_DEVICE_INIT_DELAY); + + /* Do a GET_LINE_CODING first. */ + status = _ux_host_class_cdc_acm_ioctl(cdc_acm, UX_HOST_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING, (VOID *) &line_coding); + + /* If we are done success, go on. */ + if (status == UX_SUCCESS) + { + + /* Set the default values to the device, first line coding. */ + line_coding.ux_host_class_cdc_acm_line_coding_dter = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_RATE; + line_coding.ux_host_class_cdc_acm_line_coding_stop_bit = UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT_0; + line_coding.ux_host_class_cdc_acm_line_coding_parity = UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY_NONE; + line_coding.ux_host_class_cdc_acm_line_coding_data_bits = UX_HOST_CLASS_CDC_ACM_LINE_CODING_DEFAULT_DATA_BIT; + status = _ux_host_class_cdc_acm_ioctl(cdc_acm, UX_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING, (VOID *) &line_coding); + } + + /* If we are done success, go on. */ + if (status == UX_SUCCESS) + { + + /* Set the default values to the device, line state. */ + line_state.ux_host_class_cdc_acm_line_state_rts = 1; + line_state.ux_host_class_cdc_acm_line_state_dtr = 1; + status = _ux_host_class_cdc_acm_ioctl(cdc_acm, UX_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE, (VOID *) &line_state); + } + + /* If we are done success, go on. */ + if (status == UX_SUCCESS) + { + + /* Get the capabilities of the device. We need to know if the commands are multiplexed over the comm + interface or the data interface. */ + status = _ux_host_class_cdc_acm_capabilities_get(cdc_acm); + } + } + + /* If we are done success, go on. */ + if (status == UX_SUCCESS) + { + /* Mark the cdc_acm as live now. Both interfaces need to be live. */ + cdc_acm -> ux_host_class_cdc_acm_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_ACTIVATE, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, cdc_acm, 0, 0, 0) + + /* We are done success. */ + return(UX_SUCCESS); + } + } + + /* On error case, it's possible data buffer allocated for interrupt endpoint and transfer started, stop and free it. */ + if (cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint && + cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer) + { + + /* The first transfer request has already been initiated. Abort it. */ + _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint); + + /* Free the memory for the data pointer. */ + _ux_utility_memory_free(cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer); + } + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm); + + /* Destroy the semaphore. */ + _ux_utility_semaphore_delete(&cdc_acm -> ux_host_class_cdc_acm_semaphore); + + /* Unmount instance. */ + interface -> ux_interface_class_instance = UX_NULL; + + /* Free instance. */ + _ux_utility_memory_free(cdc_acm); + + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_capabilities_get.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_capabilities_get.c new file mode 100644 index 0000000..0b614a1 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_capabilities_get.c @@ -0,0 +1,260 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_capabilities_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the entire cdc_acm configuration descriptors. */ +/* This is needed because the cdc_acm class needs to know if commands */ +/* are routed through the comm interface or the data class. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Pointer to cdc_acm class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_cdc_acm_activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_capabilities_get(UX_HOST_CLASS_CDC_ACM *cdc_acm) +{ + +UCHAR *descriptor; +UCHAR *saved_descriptor; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UX_CONFIGURATION configuration; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UINT status; +ULONG total_descriptor_length; +UCHAR descriptor_length; +UCHAR descriptor_type; +UCHAR descriptor_subtype; +ULONG interface_found; + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the descriptor. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_CONFIGURATION_DESCRIPTOR_LENGTH); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save this descriptor address since we need to free it. */ + saved_descriptor = descriptor; + + /* Create a transfer request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = UX_CONFIGURATION_DESCRIPTOR_LENGTH; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_CONFIGURATION_DESCRIPTOR_ITEM << 8; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == UX_CONFIGURATION_DESCRIPTOR_LENGTH)) + { + + /* The descriptor is in a packed format, parse it locally. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, (UCHAR *) &configuration.ux_configuration_descriptor); + + /* Now we have the configuration descriptor which will tell us how many + bytes there are in the entire descriptor. */ + total_descriptor_length = configuration.ux_configuration_descriptor.wTotalLength; + + /* Free the previous descriptor. */ + _ux_utility_memory_free(descriptor); + + /* Allocate enough memory to read all descriptors attached + to this configuration. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, total_descriptor_length); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save this descriptor address since we need to free it. */ + saved_descriptor = descriptor; + + /* Set the length we need to retrieve. */ + transfer_request -> ux_transfer_request_requested_length = total_descriptor_length; + + /* And reprogram the descriptor buffer address. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == total_descriptor_length)) + { + + /* Default is Interface descriptor not yet found. */ + interface_found = UX_FALSE; + + /* Scan the descriptor for the CDC Comm interface. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We can free the resource now. */ + _ux_utility_memory_free(saved_descriptor); + + /* Descriptor is corrupted. */ + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Process relative to descriptor type. */ + switch (descriptor_type) + { + + + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &interface_descriptor); + + /* Ensure we have the correct interface for Audio streaming. */ + if ((interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS) && + ((interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_CDC_ACM_SUBCLASS) || + (interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_CDC_DLC_SUBCLASS))) + { + + /* Mark we have found it. */ + interface_found = UX_TRUE; + + } + else + { + + /* Haven't found it. */ + interface_found = UX_FALSE; + } + break; + + + case UX_HOST_CLASS_CDC_ACM_CS_INTERFACE: + + /* First make sure we have found the correct generic interface descriptor. */ + if ((interface_found == UX_TRUE) && (descriptor_subtype == UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_DESCRIPTOR)) + { + + /* Retrieve the bmCapabilities field which indicates how ACM commands are sent to the device. */ + cdc_acm -> ux_host_class_cdc_acm_capabilities = *(descriptor + UX_HOST_CLASS_CDC_ACM_CALL_MANAGEMENT_CAPABILITIES); + + + } + break; + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We can free the resource now. */ + _ux_utility_memory_free(saved_descriptor); + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* We can free the resource now. */ + _ux_utility_memory_free(saved_descriptor); + + return(UX_SUCCESS); + } + } + + /* Free all used resources. */ + _ux_utility_memory_free(saved_descriptor); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_command.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_command.c new file mode 100644 index 0000000..b53be8f --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_command.c @@ -0,0 +1,163 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_command PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will send a command to the ACM device. The command */ +/* can be one of the following : */ +/* SET_CONTROL */ +/* SET_LINE */ +/* SEND_BREAK */ +/* */ +/* */ +/* INPUT */ +/* */ +/* acm Pointer to acm class */ +/* command command value */ +/* value value to be sent in the */ +/* command request */ +/* data_buffer buffer to be sent */ +/* data_length length of the buffer to send */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_command(UX_HOST_CLASS_CDC_ACM *cdc_acm, ULONG command, + ULONG value, UCHAR *data_buffer, ULONG data_length) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +ULONG request_direction; + + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Check the direction of the command. */ + switch (command) + { + + case UX_HOST_CLASS_CDC_ACM_REQ_SEND_ENCAPSULATED_COMMAND : + case UX_HOST_CLASS_CDC_ACM_REQ_SET_COMM_FEATURE : + case UX_HOST_CLASS_CDC_ACM_REQ_CLEAR_COMM_FEATURE : + case UX_HOST_CLASS_CDC_ACM_REQ_SET_AUX_LINE_STATE : + case UX_HOST_CLASS_CDC_ACM_REQ_SET_HOOK_STATE : + case UX_HOST_CLASS_CDC_ACM_REQ_PULSE_SETUP : + case UX_HOST_CLASS_CDC_ACM_REQ_SEND_PULSE : + case UX_HOST_CLASS_CDC_ACM_REQ_SET_PUSLE_TIME : + case UX_HOST_CLASS_CDC_ACM_REQ_RING_AUX_JACK : + case UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_CODING : + case UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_STATE : + case UX_HOST_CLASS_CDC_ACM_REQ_SEND_BREAK : + case UX_HOST_CLASS_CDC_ACM_REQ_SET_RINGER_PARMS : + case UX_HOST_CLASS_CDC_ACM_REQ_SET_OPERATION_PARMS : + case UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_PARMS : + + /* Direction is out */ + request_direction = UX_REQUEST_OUT; + break; + + + case UX_HOST_CLASS_CDC_ACM_REQ_GET_ENCAPSULATED_COMMAND : + case UX_HOST_CLASS_CDC_ACM_REQ_GET_COMM_FEATURE : + case UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_CODING : + case UX_HOST_CLASS_CDC_ACM_REQ_GET_RINGER_PARMS : + case UX_HOST_CLASS_CDC_ACM_REQ_GET_OPERATION_PARMS : + case UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_PARMS : + + /* Direction is in */ + request_direction = UX_REQUEST_IN; + break; + + + default : + + return(UX_ERROR); + + } + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + + /* Something went wrong. */ + return(status); + + /* Create a transfer_request for the request. */ + transfer_request -> ux_transfer_request_data_pointer = data_buffer; + transfer_request -> ux_transfer_request_requested_length = data_length; + transfer_request -> ux_transfer_request_function = command; + transfer_request -> ux_transfer_request_type = request_direction | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = value; + transfer_request -> ux_transfer_request_index = cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_configure.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_configure.c new file mode 100644 index 0000000..81191a6 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_configure.c @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to the */ +/* cdc_acm. Once the cdc_acm is configured, its interface will be */ +/* activated. The bulk endpoints (1 IN, 1 OUT ) and the optional */ +/* interrupt endpoint are enumerated. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Pointer to cdc_acm class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get Get interface */ +/* _ux_host_stack_device_configuration_get Get configuration */ +/* _ux_host_stack_device_configuration_select Select configuration */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_cdc_acm_activate Data Pump class activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_configure(UX_HOST_CLASS_CDC_ACM *cdc_acm) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_DEVICE *parent_device; + + + /* If the device has been configured already, we don't need to do it + again. */ + if (cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* A cdc_acm normally has one configuration. So retrieve the 1st configuration + only. */ + status = _ux_host_stack_device_configuration_get(cdc_acm -> ux_host_class_cdc_acm_device, 0, &configuration); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, cdc_acm -> ux_host_class_cdc_acm_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check the cdc_acm power source and check the parent power source for + incompatible connections. */ + if (cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* Get parent device pointer. */ + parent_device = cdc_acm -> ux_host_class_cdc_acm_device -> ux_device_parent; + + /* If the device is NULL, the parent is the root cdc_acm and we don't have to worry + if the parent is not the root cdc_acm, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration. */ + status = _ux_host_stack_device_configuration_select(configuration); + if (status != UX_SUCCESS) + return(status); + + /* If the operation went well, the cdc_acm default alternate setting for the cdc_acm interface is + active and the interrupt endpoint is now enabled. We have to memorize the first interface since + the interrupt endpoint is hooked to it. */ + status = _ux_host_stack_configuration_interface_get(configuration, 0, 0, &cdc_acm -> ux_host_class_cdc_acm_interface); + if (status != UX_SUCCESS) + { + + /* Store the instance in the interface container, this is for the USB stack + when it needs to invoke the class. */ + cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_class_instance = (VOID *) cdc_acm; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_deactivate.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_deactivate.c new file mode 100644 index 0000000..4ea0de0 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_deactivate.c @@ -0,0 +1,170 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the cdc_acm has been */ +/* removed from the bus either directly or indirectly. The bulk in\out */ +/* and optional interrupt pipes will be destroyed and the instance */ +/* removed. */ +/* */ +/* INPUT */ +/* */ +/* command CDC ACM class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_utility_thread_schedule_other Schedule other threads */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_cdc_acm_entry Entry of cdc_acm class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_CDC_ACM *cdc_acm; +UX_TRANSFER *transfer_request; +UINT status; + + /* Get the instance for this class. */ + cdc_acm = (UX_HOST_CLASS_CDC_ACM *) command -> ux_host_class_command_instance; + + /* The cdc_acm is being shut down. */ + cdc_acm -> ux_host_class_cdc_acm_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&cdc_acm -> ux_host_class_cdc_acm_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* If we have the Control Class, we only unmount the interrupt endpoint if it is active. */ + if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS) + { + + /* If the interrupt endpoint is defined, clean any pending transfer. */ + if (cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint != UX_NULL) + { + transfer_request = &cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint -> ux_endpoint_transfer_request; + + /* And abort any transfer. */ + _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint); + + /* Free data buffer for the interrupt transfer. */ + _ux_utility_memory_free(transfer_request -> ux_transfer_request_data_pointer); + } + } + else + { + + /* We come to this point when the device has been extracted and this is the data class. + So there may have been a transaction being scheduled. + We make sure the transaction has been completed by the controller driver. + When the device is extracted, the controller tries multiple times the transaction and retires it + with a DEVICE_NOT_RESPONDING error code. + + First we take care of endpoint IN. */ + transfer_request = &cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint); + + /* Then endpoint OUT. */ + transfer_request = &cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + + /* We need to abort transactions on the bulk Out pipe. */ + _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint); + + } + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm); + + /* Destroy the semaphore. */ + _ux_utility_semaphore_delete(&cdc_acm -> ux_host_class_cdc_acm_semaphore); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, cdc_acm -> ux_host_class_cdc_acm_class, (VOID *) cdc_acm); + } + + /* Free the cdc_acm instance memory. */ + _ux_utility_memory_free(cdc_acm); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_DEACTIVATE, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(cdc_acm); + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_endpoints_get.c new file mode 100644 index 0000000..69fb96d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_endpoints_get.c @@ -0,0 +1,212 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function distinguishes for either the Data or Control Class. */ +/* For the data class, we mount the bulk in and bulk out endpoints. */ +/* For the control class, we mount the optional interrupt endpoint. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Pointer to cdc_acm class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_cdc_acm_activate Activate cdc_acm class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_endpoints_get(UX_HOST_CLASS_CDC_ACM *cdc_acm) +{ + +UINT status; +UINT endpoint_index; +UX_ENDPOINT *endpoint; +UX_TRANSFER *transfer_request; + + + /* Check what interface we are mounting. */ + if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_DATA_CLASS) + { + + /* Search the bulk OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get interface endpoint. */ + status = _ux_host_stack_interface_endpoint_get(cdc_acm -> ux_host_class_cdc_acm_interface, endpoint_index, &endpoint); + + /* Check if endpoint is bulk and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the OUT direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + + /* We have found the bulk endpoint, save it. */ + cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint = endpoint; + + /* If found all, we break. */ + if (cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint) + break; + } + + /* Check if endpoint is bulk and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the bulk endpoint, save it. */ + cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint = endpoint; + + /* If found all, we break. */ + if (cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint) + break; + } + } + + /* The both bulk endpoints are mandatory. */ + if (cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint == UX_NULL || + cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + } + else + { + /* Search the Interrupt endpoint. It is attached to the interface container of the control interface. It is not mandatory. */ + for (endpoint_index = 0; endpoint_index < cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + status = _ux_host_stack_interface_endpoint_get(cdc_acm -> ux_host_class_cdc_acm_interface, endpoint_index, &endpoint); + + /* Check if endpoint is Interrupt and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the interrupt endpoint, save it. */ + cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint = endpoint; + + /* The endpoint is correct, Fill in the transfer request with the length requested for this endpoint. */ + transfer_request = &cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint -> ux_endpoint_transfer_request; + transfer_request -> ux_transfer_request_requested_length = cdc_acm -> ux_host_class_cdc_acm_interrupt_endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + transfer_request -> ux_transfer_request_actual_length = 0; + + /* The direction is always IN for the CDC interrupt endpoint. */ + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN; + + /* There is a callback function associated with the transfer request, so we need the class instance. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) cdc_acm; + + /* Interrupt transactions have a completion routine. */ + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_cdc_acm_transfer_request_completed; + + /* Obtain a buffer for this transaction. The buffer will always be reused. */ + transfer_request -> ux_transfer_request_data_pointer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + transfer_request -> ux_transfer_request_requested_length); + + /* If the endpoint is available and we have memory, we start the interrupt endpoint. */ + if (transfer_request -> ux_transfer_request_data_pointer != UX_NULL) + { + + /* The transfer on the interrupt endpoint can be started. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check error, if endpoint interrupt IN transfer not successful, do not proceed. */ + if (status != UX_SUCCESS) + + /* Error, do not proceed. */ + return(status); + } + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We must return an error. */ + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + break; + } + } + } + + /* All endpoints have been mounted. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_entry.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_entry.c new file mode 100644 index 0000000..b74f88f --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_entry.c @@ -0,0 +1,152 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Acm Cdc Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the cdc_acm class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* cdc_acm on the bus or when the USB cdc_acm is removed. */ +/* */ +/* A CDC class can have multiple interfaces, one for Control and one */ +/* for Data. Here we filter for the Communication Class with ACM */ +/* subclass and the Communication Data Class. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* command Acm Cdc class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_cdc_acm_activate Activate cdc_acm class */ +/* _ux_host_class_cdc_acm_deactivate Deactivate cdc_acm class */ +/* */ +/* CALLED BY */ +/* */ +/* Acm Cdc Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) && + ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_DATA_CLASS) || + ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) && + (command -> ux_host_class_command_subclass == UX_HOST_CLASS_CDC_ACM_SUBCLASS)) || + ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) && + (command -> ux_host_class_command_subclass == UX_HOST_CLASS_CDC_DLC_SUBCLASS)))) + { + /* Check for IAD presence. */ + if ((command -> ux_host_class_command_iad_class == 0) && (command -> ux_host_class_command_iad_subclass == 0)) + + /* No IAD, we accept this class. */ + return(UX_SUCCESS); + + else + { + + if ((command -> ux_host_class_command_iad_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) && + (command -> ux_host_class_command_iad_subclass == UX_HOST_CLASS_CDC_ACM_SUBCLASS)) + + /* There is an IAD and this is for CDC-ACM. */ + return(UX_SUCCESS); + + else + + /* The IAD does not match with CDC-ACM. */ + return(UX_NO_CLASS_MATCH); + } + } + + else + + /* No match. */ + return(UX_NO_CLASS_MATCH); + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_cdc_acm_activate(command); + return(status); + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_cdc_acm_deactivate(command); + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_ioctl.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_ioctl.c new file mode 100644 index 0000000..ea54824 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_ioctl.c @@ -0,0 +1,294 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_ioctl PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the ioctl entry point for the application to */ +/* configure the ACM device. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* acm Pointer to acm class */ +/* ioctl_function ioctl function */ +/* parameter pointer to structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort transfer */ +/* _ux_host_class_cdc_acm_command Send command to acm device */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_long_put Put 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_ioctl(UX_HOST_CLASS_CDC_ACM *cdc_acm, ULONG ioctl_function, + VOID *parameter) +{ + +UINT status; +UCHAR *data_buffer; +UX_HOST_CLASS_CDC_ACM_LINE_CODING *line_coding; +UX_HOST_CLASS_CDC_ACM_LINE_STATE *line_state; +VOID (*callback_function) (struct UX_HOST_CLASS_CDC_ACM_STRUCT *, ULONG, ULONG ); +ULONG value; + + /* Ensure the instance is valid. */ + if ((cdc_acm -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE) && + (cdc_acm -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_MOUNTING)) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* The command request will tell us what we need to do here. */ + switch (ioctl_function) + { + + case UX_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_CODING, cdc_acm, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Allocate some cache safe memory for the control command. */ + data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH); + + /* Check if error. Return with error if no memory could be allocated. */ + if (data_buffer == UX_NULL) + + /* Do not proceed. Set error code. */ + status = UX_MEMORY_INSUFFICIENT; + else + { + + /* Build the buffer from the calling parameter. Cast the calling parameter. */ + line_coding = (UX_HOST_CLASS_CDC_ACM_LINE_CODING *) parameter; + + /* Put the data rate. */ + _ux_utility_long_put(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_RATE, + line_coding -> ux_host_class_cdc_acm_line_coding_dter); + + /* Then the stop bit. */ + *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT) = + (UCHAR) line_coding -> ux_host_class_cdc_acm_line_coding_stop_bit; + + /* Then the parity. */ + *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY) = + (UCHAR) line_coding -> ux_host_class_cdc_acm_line_coding_parity; + + /* Finally the data bits. */ + *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_DATA_BIT) = + (UCHAR) line_coding -> ux_host_class_cdc_acm_line_coding_data_bits; + + /* Send the command to the device. */ + status = _ux_host_class_cdc_acm_command(cdc_acm, UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_CODING, + 0, data_buffer, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH); + + /* We free the resources allocated no matter what. */ + _ux_utility_memory_free(data_buffer); + } + break; + + case UX_HOST_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_GET_LINE_CODING, cdc_acm, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Allocate some cache safe memory for the control command. */ + data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH); + + /* Check if error. Return with error if no memory could be allocated. */ + if (data_buffer == UX_NULL) + + /* Do not proceed. Set error code. */ + status = UX_MEMORY_INSUFFICIENT; + else + { + + /* Send the command to the device. */ + status = _ux_host_class_cdc_acm_command(cdc_acm, UX_HOST_CLASS_CDC_ACM_REQ_GET_LINE_CODING, + 0, data_buffer, UX_HOST_CLASS_CDC_ACM_LINE_CODING_LENGTH); + + /* Fill in the calling buffer if the result is successful. */ + if (status == UX_SUCCESS) + { + + /* Build the buffer from the calling parameter. Cast the calling parameter. */ + line_coding = (UX_HOST_CLASS_CDC_ACM_LINE_CODING *) parameter; + + /* Get the data rate. */ + line_coding -> ux_host_class_cdc_acm_line_coding_dter = _ux_utility_long_get(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_RATE); + + /* Then the stop bit. */ + line_coding -> ux_host_class_cdc_acm_line_coding_stop_bit = + (ULONG) *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_STOP_BIT); + + /* Then the parity. */ + line_coding -> ux_host_class_cdc_acm_line_coding_parity = + (ULONG) *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_PARITY); + + /* Finally the data bits. */ + line_coding -> ux_host_class_cdc_acm_line_coding_data_bits = + (ULONG) *(data_buffer + UX_HOST_CLASS_CDC_ACM_LINE_CODING_DATA_BIT); + } + + /* We free the resources allocated no matter what. */ + _ux_utility_memory_free(data_buffer); + } + break; + + case UX_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_SET_LINE_STATE, cdc_acm, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Cast the calling parameter. */ + line_state = (UX_HOST_CLASS_CDC_ACM_LINE_STATE *) parameter; + + /* Build the value field. */ + value = (line_state -> ux_host_class_cdc_acm_line_state_dtr | + (line_state -> ux_host_class_cdc_acm_line_state_rts << 1)); + + /* Send the command to the device. */ + status = _ux_host_class_cdc_acm_command(cdc_acm, UX_HOST_CLASS_CDC_ACM_REQ_SET_LINE_STATE, + value, UX_NULL,0); + break; + + case UX_HOST_CLASS_CDC_ACM_IOCTL_SEND_BREAK : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_SEND_BREAK, cdc_acm, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Build the value field. */ + value = *((ULONG *) parameter); + + /* Send the command to the device. */ + status = _ux_host_class_cdc_acm_command(cdc_acm, UX_HOST_CLASS_CDC_ACM_REQ_SEND_BREAK, + value, UX_NULL,0); + break; + + + + case UX_HOST_CLASS_CDC_ACM_IOCTL_ABORT_IN_PIPE : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_ABORT_IN_PIPE, cdc_acm, cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint); + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_CDC_ACM_IOCTL_ABORT_OUT_PIPE : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_ABORT_OUT_PIPE, cdc_acm, cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to abort transactions on the bulk Out pipe. */ + _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint); + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_CDC_ACM_IOCTL_NOTIFICATION_CALLBACK : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_NOTIFICATION_CALLBACK, cdc_acm, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Register a callback when the line state has changed. */ + callback_function = ((VOID (*) (struct UX_HOST_CLASS_CDC_ACM_STRUCT *, ULONG, ULONG )) (ALIGN_TYPE)parameter); + cdc_acm -> ux_host_class_cdc_acm_device_status_change_callback = callback_function; + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_CDC_ACM_IOCTL_GET_DEVICE_STATUS : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_IOCTL_GET_DEVICE_STATUS, cdc_acm, cdc_acm -> ux_host_class_cdc_acm_device_state, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Return the device status. */ + *((ULONG *) parameter) = cdc_acm -> ux_host_class_cdc_acm_device_state; + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Function not supported. Return an error. */ + status = UX_FUNCTION_NOT_SUPPORTED; + } + + /* Return status to caller. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_read.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_read.c new file mode 100644 index 0000000..5f62be2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_read.c @@ -0,0 +1,200 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** ACM CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the cdc_acm interface. The call is */ +/* blocking and only returns when there is either an error or when */ +/* the transfer is complete. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Pointer to cdc_acm class */ +/* data_pointer Pointer to buffer */ +/* requested_length Requested data read */ +/* actual_length Actual data read */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_read (UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_READ, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (cdc_acm -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* As further protection, we must ensure this instance of the interface is the data interface and not + the control interface ! */ + if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass != UX_HOST_CLASS_CDC_DATA_CLASS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Start by resetting the actual length of the transfer to zero. */ + *actual_length = 0; + + /* Get the pointer to the bulk in endpoint in the transfer_request. */ + transfer_request = &cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Perform a transfer on the bulk in endpoint until either the transfer is + completed or until there is an error. */ + while (requested_length) + { + + /* Program the maximum authorized length for this transfer request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer_request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_CDC_ACM_CLASS_TRANSFER_TIMEOUT); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer request in case some data was actually received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked. */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually received and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Return success to caller. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to receive. */ + requested_length -= transfer_request_length; + } + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_callback.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_callback.c new file mode 100644 index 0000000..dbf6477 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_callback.c @@ -0,0 +1,142 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** ACM CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_reception_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the callback from the USBX transfer functions, */ +/* it is called when a full or partial transfer has been done for a */ +/* bulk in transfer. It calls back the application. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_cdc_acm_reception_callback (UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_CDC_ACM *cdc_acm; +UX_HOST_CLASS_CDC_ACM_RECEPTION *cdc_acm_reception; + + /* Get the class instance for this transfer request. */ + cdc_acm = (UX_HOST_CLASS_CDC_ACM *) transfer_request -> ux_transfer_request_class_instance; + + /* Get the pointer to the acm reception structure. */ + cdc_acm_reception = cdc_acm -> ux_host_class_cdc_acm_reception; + + /* Check the state of the transfer. If there is an error, we do not proceed with this report. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* The reception is stopped. */ + cdc_acm_reception -> ux_host_class_cdc_acm_reception_state = UX_HOST_CLASS_CDC_ACM_RECEPTION_STATE_STOPPED; + + /* We do not proceed. */ + return; + + } + + /* Move to the next reception buffer. Check if we are at the end of the application buffer. */ + if (cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_head + cdc_acm_reception -> ux_host_class_cdc_acm_reception_block_size >= + cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_buffer + cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_buffer_size) + + /* Program the head to be at the beginning of the application buffer. */ + cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_head = cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_buffer; + + else + + /* Program the head to be after the current buffer. */ + cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_head += cdc_acm_reception -> ux_host_class_cdc_acm_reception_block_size; + + /* OVERFLOW check: if the head reaches the tail buffer that contains reception data */ + if (cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_tail == cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_head) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_BUFFER_OVERFLOW, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We have an overflow. We cannot continue. Report to the application. */ + cdc_acm_reception -> ux_host_class_cdc_acm_reception_callback(cdc_acm, UX_BUFFER_OVERFLOW, UX_NULL, 0); + + /* And stop the transfer in progress flag. */ + cdc_acm_reception -> ux_host_class_cdc_acm_reception_state = UX_HOST_CLASS_CDC_ACM_RECEPTION_STATE_STOPPED; + + return; + } + + /* We need to report this transfer to the application. */ + cdc_acm_reception -> ux_host_class_cdc_acm_reception_callback(cdc_acm, + transfer_request -> ux_transfer_request_completion_code, + transfer_request -> ux_transfer_request_data_pointer, + transfer_request -> ux_transfer_request_actual_length); + + /* Set data pointer to the next reception buffer. */ + transfer_request -> ux_transfer_request_data_pointer = cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_head; + + /* Arm another transfer. */ + _ux_host_stack_transfer_request(transfer_request); + + /* There is no status to be reported back to the stack. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_start.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_start.c new file mode 100644 index 0000000..c9ed01b --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_start.c @@ -0,0 +1,142 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** ACM CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_reception_start PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a reception with the ACM modem. This mechanism */ +/* allows for non blocking calls based on a packet orientated round */ +/* robbin buffer. When a packet is fully or partially received, an */ +/* application callback function is invoked and a new transfer request */ +/* is rescheduled. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Pointer to cdc_acm class */ +/* cdc_acm_reception Pointer to reception struct */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_reception_start (UX_HOST_CLASS_CDC_ACM *cdc_acm, + UX_HOST_CLASS_CDC_ACM_RECEPTION *cdc_acm_reception) +{ + +UX_TRANSFER *transfer_request; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_RECEPTION_START, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (cdc_acm -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* As further protection, we must ensure this instance of the interface is the data interface and not + the control interface ! */ + if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass != UX_HOST_CLASS_CDC_DATA_CLASS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Start by aligning the head and tail of buffers to the same address supplied by the application. */ + cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_head = cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_buffer; + cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_tail = cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_buffer; + + /* Get the pointer to the bulk in endpoint in the transfer_request. */ + transfer_request = &cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Initialize the transfer request. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) cdc_acm; + transfer_request -> ux_transfer_request_data_pointer = cdc_acm_reception -> ux_host_class_cdc_acm_reception_data_head; + transfer_request -> ux_transfer_request_requested_length = cdc_acm_reception -> ux_host_class_cdc_acm_reception_block_size; + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_cdc_acm_reception_callback; + + /* Save the acm reception structure in the acm structure. */ + cdc_acm -> ux_host_class_cdc_acm_reception = cdc_acm_reception; + + /* And declare we have a transfer in progress. */ + cdc_acm_reception -> ux_host_class_cdc_acm_reception_state = UX_HOST_CLASS_CDC_ACM_RECEPTION_STATE_STARTED; + + /* Arm a first transfer on the bulk in endpoint. There is a callback to this function so we return to the caller + right away. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* We do not know if the first transfer was successful yet. If the status is not OK, we need to stop the transfer + in progress flag. */ + if (status != UX_SUCCESS) + cdc_acm_reception -> ux_host_class_cdc_acm_reception_state = UX_HOST_CLASS_CDC_ACM_RECEPTION_STATE_STOPPED; + + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_stop.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_stop.c new file mode 100644 index 0000000..73af01a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_reception_stop.c @@ -0,0 +1,134 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** ACM CDC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_reception_stop PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function stops background reception previously started by */ +/* ux_host_class_cdc_acm_reception_start. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Pointer to cdc_acm class */ +/* cdc_acm_reception Pointer to reception struct */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort transfer */ +/* _ux_utility_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_reception_stop(UX_HOST_CLASS_CDC_ACM *cdc_acm, + UX_HOST_CLASS_CDC_ACM_RECEPTION *cdc_acm_reception) +{ + +UX_TRANSFER *transfer_request; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_RECEPTION_STOP, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (cdc_acm -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* As further protection, we must ensure this instance of the interface is the data interface and not + the control interface ! */ + if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass != UX_HOST_CLASS_CDC_DATA_CLASS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Check if we do have transfers for this application. If none, nothing to do. */ + if (cdc_acm_reception -> ux_host_class_cdc_acm_reception_state == UX_HOST_CLASS_CDC_ACM_RECEPTION_STATE_STOPPED) + return(UX_SUCCESS); + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint); + + /* Declare the reception stopped. */ + cdc_acm_reception -> ux_host_class_cdc_acm_reception_state = UX_HOST_CLASS_CDC_ACM_RECEPTION_STATE_STOPPED; + + /* Obtain pointer to transfer request. */ + transfer_request = &cdc_acm -> ux_host_class_cdc_acm_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Reset the completion callback function. */ + transfer_request -> ux_transfer_request_completion_function = UX_NULL; + + /* Clear semaphore counts that were (incorrectly) increased during each transfer + completion. */ + while (transfer_request -> ux_transfer_request_semaphore.tx_semaphore_count) + _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, 0); + + /* This function never really fails. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_transfer_request_completed.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_transfer_request_completed.c new file mode 100644 index 0000000..3c54429 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_transfer_request_completed.c @@ -0,0 +1,111 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC_ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_transfer_request_completed PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the completion thread when a transfer */ +/* request has been completed either because the transfer is */ +/* successful or there was an error. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_utility_short_get Get 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* USBX stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_cdc_acm_transfer_request_completed(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_CDC_ACM *cdc_acm; +ULONG notification_type; +ULONG notification_value; + + + /* Get the class instance for this transfer request. */ + cdc_acm = (UX_HOST_CLASS_CDC_ACM *) transfer_request -> ux_transfer_request_class_instance; + + /* Check the state of the transfer. If there is an error, we do not proceed with this notification. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + + /* We do not proceed. */ + return; + + /* Increment the notification count. */ + cdc_acm -> ux_host_class_cdc_acm_notification_count++; + + /* Get the notification. */ + notification_type = (ULONG) *(transfer_request -> ux_transfer_request_data_pointer + UX_HOST_CLASS_CDC_ACM_NPF_NOTIFICATION_TYPE); + + /* And the value. */ + notification_value = (ULONG) _ux_utility_short_get(transfer_request -> ux_transfer_request_data_pointer + UX_HOST_CLASS_CDC_ACM_NPF_VALUE); + + /* If there is a callback present, invoke it. */ + if (cdc_acm -> ux_host_class_cdc_acm_device_status_change_callback != UX_NULL) + + /* There is a callback, send the status change to the application. */ + cdc_acm -> ux_host_class_cdc_acm_device_status_change_callback(cdc_acm, notification_type, notification_value); + + /* Reactivate the CDC_ACM interrupt pipe. */ + _ux_host_stack_transfer_request(transfer_request); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_acm_write.c b/common/usbx_host_classes/src/ux_host_class_cdc_acm_write.c new file mode 100644 index 0000000..ba2e7fa --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_acm_write.c @@ -0,0 +1,200 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ACM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_acm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the cdc_acm interface. The call is blocking */ +/* and only returns when there is either an error or when the transfer */ +/* is complete. */ +/* */ +/* INPUT */ +/* */ +/* cdc_acm Pointer to cdc_acm class */ +/* data_pointer Pointer to data to write */ +/* requested_length Length of data to write */ +/* actual_length Actual length of data written */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_acm_write(UX_HOST_CLASS_CDC_ACM *cdc_acm, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ACM_WRITE, cdc_acm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (cdc_acm -> ux_host_class_cdc_acm_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* As further protection, we must ensure this instance of the interface is the data interface and not + the control interface ! */ + if (cdc_acm -> ux_host_class_cdc_acm_interface -> ux_interface_descriptor.bInterfaceClass != UX_HOST_CLASS_CDC_DATA_CLASS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_acm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Start by resetting the actual length of the transfer. */ + *actual_length = 0; + + /* Get the pointer to the bulk out endpoint transfer request. */ + transfer_request = &cdc_acm -> ux_host_class_cdc_acm_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Perform a transfer on the bulk out endpoint until either the transfer is + completed or when there is an error. */ + while (requested_length) + { + + /* Program the maximum authorized length for this transfer_request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_CDC_ACM_CLASS_TRANSFER_TIMEOUT); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer_request in case some data actually went out. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be sent. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually sent and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Return success. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to send out. */ + requested_length -= transfer_request_length; + } + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_activate.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_activate.c new file mode 100644 index 0000000..e448107 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_activate.c @@ -0,0 +1,373 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_ecm.h" +#include "ux_host_stack.h" + +UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_ecm_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates the cdc_ecm instance, configure the device. */ +/* */ +/* INPUT */ +/* */ +/* command CDC ECM class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_host_class_cdc_ecm_endpoints_get Get endpoints of cdc_ecm */ +/* _ux_host_class_cdc_ecm_mac_address_get Get MAC address */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_utility_thread_create Create thread */ +/* _ux_utility_thread_delete Delete thread */ +/* _ux_utility_thread_resume Resume thread */ +/* _ux_network_driver_activate Activate NetX USB interface*/ +/* nx_packet_pool_create Create NetX packet pool */ +/* nx_packet_pool_delete Delete NetX packet pool */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_cdc_ecm_entry Entry of cdc_ecm class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_ecm_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_INTERFACE *interface; +UX_HOST_CLASS_CDC_ECM *cdc_ecm; +UINT status; +UX_TRANSFER *transfer_request; +ULONG physical_address_msw = 0; +ULONG physical_address_lsw = 0; +UX_INTERFACE *control_interface; +UX_INTERFACE *cur_interface; + + /* The CDC ECM class is always activated by the interface descriptor and not the + device descriptor. */ + interface = (UX_INTERFACE *) command -> ux_host_class_command_container; + + /* Is this the control interface? */ + if (interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS) + { + + /* We ignore the control interface. All activation is performed when + we receive the data interface. */ + return(UX_SUCCESS); + } + + /* Obtain memory for this class instance. */ + cdc_ecm = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, sizeof(UX_HOST_CLASS_CDC_ECM)); + if (cdc_ecm == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance. */ + cdc_ecm -> ux_host_class_cdc_ecm_class = command -> ux_host_class_command_class_ptr; + + /* Store the device container into the cdc_ecm class instance. */ + cdc_ecm -> ux_host_class_cdc_ecm_device = interface -> ux_interface_configuration -> ux_configuration_device; + + /* Store the interface container into the cdc_acm class instance. */ + cdc_ecm -> ux_host_class_cdc_ecm_interface_data = interface; + + /* We need to link the data and control interfaces together. In order + to do this, we first need to find the control interface. Per the spec, + it should be behind this one. */ + + /* Set the current interface to the second interface. */ + cur_interface = interface -> ux_interface_configuration -> ux_configuration_first_interface; + + /* Initialize to null. */ + control_interface = UX_NULL; + + /* Loop through all the interfaces until we find the current data interface. */ + while (cur_interface != interface) + { + + /* Is this a control interface? */ + if (cur_interface -> ux_interface_descriptor.bInterfaceClass == UX_HOST_CLASS_CDC_CONTROL_CLASS) + { + + /* Save it. */ + control_interface = cur_interface; + } + + /* Advance current interface. */ + cur_interface = cur_interface -> ux_interface_next_interface; + } + + /* Did we not find the control interface? */ + if (control_interface == UX_NULL) + { + + /* This in an invalid descriptor. */ + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error. */ + status = UX_DESCRIPTOR_CORRUPTED; + } + else + { + + /* We found the control interface. */ + status = UX_SUCCESS; + } + + if (status == UX_SUCCESS) + { + + /* Save the control interface. */ + cdc_ecm -> ux_host_class_cdc_ecm_interface_control = (UX_INTERFACE *) control_interface; + + /* Get the cdc_ecm endpoint(s) on the interface. */ + status = _ux_host_class_cdc_ecm_endpoints_get(cdc_ecm); + } + + if (status == UX_SUCCESS) + { + + /* Allocate a Thread stack. */ + cdc_ecm -> ux_host_class_cdc_ecm_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + if (cdc_ecm -> ux_host_class_cdc_ecm_thread_stack == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + if (status == UX_SUCCESS) + { + + /* Allocate some packet pool for reception. + * UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE overflow has been checked by + * UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE_ASSERT outside of function. + */ + cdc_ecm -> ux_host_class_cdc_ecm_pool_memory = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE); + if (cdc_ecm -> ux_host_class_cdc_ecm_pool_memory == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + if (status == UX_SUCCESS) + { + + /* Create the semaphore for aborting bulk in transfers. */ + status = _ux_utility_semaphore_create(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, + "host CDC-ECM bulk in wait semaphore", 0); + if (status == UX_SUCCESS) + { + + /* Create the semaphore for aborting bulk out transfers. */ + status = _ux_utility_semaphore_create(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore, + "host CDC-ECM bulk out wait semaphore", 0); + if (status == UX_SUCCESS) + { + + /* Create the semaphore to wake up the CDC ECM thread. */ + status = _ux_utility_semaphore_create(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore, "host CDC-ECM interrupt notification semaphore", 0); + if (status == UX_SUCCESS) + { + + /* Create a packet pool. */ + status = nx_packet_pool_create(&cdc_ecm -> ux_host_class_cdc_ecm_packet_pool, "host CDC-ECM packet pool", + UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE, cdc_ecm -> ux_host_class_cdc_ecm_pool_memory, UX_HOST_CLASS_CDC_ECM_NX_ETHERNET_POOL_ALLOCSIZE); + if (status == UX_SUCCESS) + { + + /* Create the cdc_ecm class thread. We do not start it yet. */ + status = _ux_utility_thread_create(&cdc_ecm -> ux_host_class_cdc_ecm_thread, + "ux_host_cdc_ecm_thread", _ux_host_class_cdc_ecm_thread, + (ULONG) (ALIGN_TYPE) cdc_ecm, + cdc_ecm -> ux_host_class_cdc_ecm_thread_stack, + UX_THREAD_STACK_SIZE, + UX_THREAD_PRIORITY_CLASS, + UX_THREAD_PRIORITY_CLASS, + TX_NO_TIME_SLICE, TX_DONT_START); + if (status == UX_SUCCESS) + { + + UX_THREAD_EXTENSION_PTR_SET(&(cdc_ecm -> ux_host_class_cdc_ecm_thread), cdc_ecm) + + /* We now need to retrieve the MAC address of the node which is embedded in the ECM descriptor. + We will parse the entire configuration descriptor of the device and look for the ECM Ethernet Networking Functional Descriptor. */ + status = _ux_host_class_cdc_ecm_mac_address_get(cdc_ecm); + + if (status == UX_SUCCESS) + { + + /* Setup the physical address of this IP instance. */ + physical_address_msw = (ULONG)((cdc_ecm -> ux_host_class_cdc_ecm_node_id[0] << 8) | (cdc_ecm -> ux_host_class_cdc_ecm_node_id[1])); + physical_address_lsw = (ULONG)((cdc_ecm -> ux_host_class_cdc_ecm_node_id[2] << 24) | (cdc_ecm -> ux_host_class_cdc_ecm_node_id[3] << 16) | + (cdc_ecm -> ux_host_class_cdc_ecm_node_id[4] << 8) | (cdc_ecm -> ux_host_class_cdc_ecm_node_id[5])); + + /* The ethernet link is down by default. */ + cdc_ecm -> ux_host_class_cdc_ecm_link_state = UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN; + } + + if (status == UX_SUCCESS) + { + + /* Register this interface to the NetX USB interface broker. */ + status = _ux_network_driver_activate((VOID *) cdc_ecm, _ux_host_class_cdc_ecm_write, + &cdc_ecm -> ux_host_class_cdc_ecm_network_handle, + physical_address_msw, physical_address_lsw); + } + + if (status == UX_SUCCESS) + { + + /* Mark the cdc_ecm data instance as live now. */ + cdc_ecm -> ux_host_class_cdc_ecm_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* This instance of the device must also be stored in the interface container. */ + interface -> ux_interface_class_instance = (VOID *) cdc_ecm; + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); + + /* Start the interrupt pipe now if it exists. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint != UX_NULL) + { + + /* Obtain the transfer request from the interrupt endpoint. */ + transfer_request = &cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request; + status = _ux_host_stack_transfer_request(transfer_request); + } + + if (status == UX_SUCCESS) + { + + /* Activation is complete. */ + + /* Now we can start the CDC-ECM thread. */ + _ux_utility_thread_resume(&cdc_ecm -> ux_host_class_cdc_ecm_thread); + + /* We need to inform the application if a function has been programmed + in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. Note that the application should + wait until the link state is up until using this instance. The + link state is changed to up by the CDC-ECM thread, which isn't + started until after the data interface has been processed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ECM_ACTIVATE, cdc_ecm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, cdc_ecm, 0, 0, 0) + + /* Activation was successful. */ + return(UX_SUCCESS); + } + + /* Error starting interrupt endpoint. */ + + /* Destroy this class instance. */ + _ux_host_stack_class_instance_destroy(cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); + + /* Unmount instance. */ + interface -> ux_interface_class_instance = UX_NULL; + } + + /* Delete CDC-ECM thread. */ + _ux_utility_thread_delete(&cdc_ecm -> ux_host_class_cdc_ecm_thread); + } + + /* Delete packet pool. */ + nx_packet_pool_delete(&cdc_ecm -> ux_host_class_cdc_ecm_packet_pool); + } + else + { + + /* Packet pool creation failed. Notify application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ENUMERATOR, status); + } + + /* Delete interrupt notification semaphore. */ + _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); + } + + /* Delete class-level bulk out semaphore. */ + _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore); + } + + /* Delete class-level bulk in semaphore. */ + _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); + } + } + + /* An error occurred. We must clean up resources. */ + + if (cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint != UX_NULL && + cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer != UX_NULL) + _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer); + + if (cdc_ecm -> ux_host_class_cdc_ecm_pool_memory != UX_NULL) + _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_pool_memory); + + if (cdc_ecm -> ux_host_class_cdc_ecm_thread_stack != UX_NULL) + _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_thread_stack); + + _ux_utility_memory_free(cdc_ecm); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_deactivate.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_deactivate.c new file mode 100644 index 0000000..6b991b9 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_deactivate.c @@ -0,0 +1,203 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_ecm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_ecm_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the cdc_ecm has been */ +/* removed from the bus either directly or indirectly. The bulk in\out */ +/* and interrupt pipes will be destroyed and the instance */ +/* removed. */ +/* */ +/* INPUT */ +/* */ +/* command CDC ECM class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_cdc_ecm_entry Entry of cdc_ecm class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_ecm_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +TX_INTERRUPT_SAVE_AREA + +UX_HOST_CLASS_CDC_ECM *cdc_ecm; +UX_TRANSFER *transfer_request; + + /* This must be the data interface, since the control interface doesn't have + a class instance. */ + + /* Get the control instance for this class. */ + cdc_ecm = (UX_HOST_CLASS_CDC_ECM *) command -> ux_host_class_command_instance; + + /* The cdc_ecm is being shut down. */ + cdc_ecm -> ux_host_class_cdc_ecm_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* If the interrupt endpoint is defined, abort transfers so the link state + doesn't change. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint != UX_NULL) + { + + /* Get the transfer request. */ + transfer_request = &cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request; + + /* Abort any transfers. */ + _ux_host_stack_transfer_request_abort(transfer_request); + } + + /* Check if link was up to see if we should clean the transmit queue. If + the link is pending down, that means the CDC-ECM thread is in the process + of cleaning the transmit queue. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_link_state == UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP) + + _ux_host_class_cdc_ecm_transmit_queue_clean(cdc_ecm); + + /* Get the bulk in transfer request. */ + transfer_request = &cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Now abort all transfers. It's possible we're executing right before the transfer + is armed. If this is the case, then the transfer will not be aborted if we do the abort right now; instead, + we should wait until after the transfer is armed. We must look at the CDC-ECM thread's state. */ + + /* Disable interrupts while we check the link state and possibly set our state. */ + TX_DISABLE + + /* Is it in the process of checking the link state and arming the transfer? */ + if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process == UX_TRUE) + { + + /* Yes. We must wait for it to finish arming the transfer. */ + + /* Let the CDC-ECM thread know we're waiting so it can wake us up. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish = UX_TRUE; + + /* Restore interrupts. */ + TX_RESTORE + + /* Wait for the transfer to be armed, or possibly an error. The CDC-ECM thread will wake us up. */ + _ux_utility_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, UX_WAIT_FOREVER); + + /* We're no longer waiting. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish = UX_FALSE; + } + else + { + + /* Restore interrupts. */ + TX_RESTORE + } + + /* Now we can abort the transfer. */ + _ux_host_stack_transfer_request_abort(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_endpoint -> ux_endpoint_transfer_request); + + /* De-register this interface to the NetX USB interface broker. */ + _ux_network_driver_deactivate((VOID *) cdc_ecm, cdc_ecm -> ux_host_class_cdc_ecm_network_handle); + + /* Destroy the control instance. */ + _ux_host_stack_class_instance_destroy(cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); + + /* Now wait for all threads to leave the instance before freeing the resources. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Free the memory used by the interrupt endpoint. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint != UX_NULL) + _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer); + + /* Destroy the link monitoring thread. We should do this before destroying + the notification semaphore so that it does not run due to semaphore deletion. */ + _ux_utility_thread_delete(&cdc_ecm -> ux_host_class_cdc_ecm_thread); + + /* Free the CDC-ECM thread's stack memory. */ + _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_thread_stack); + + /* Destroy the bulk semaphores. */ + _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore); + _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); + + /* Destroy the notification semaphore. */ + _ux_utility_semaphore_delete(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); + + /* Delete the packet pool. */ + nx_packet_pool_delete(&cdc_ecm -> ux_host_class_cdc_ecm_packet_pool); + + /* Free this pool of packets. */ + _ux_utility_memory_free(cdc_ecm -> ux_host_class_cdc_ecm_pool_memory); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, cdc_ecm -> ux_host_class_cdc_ecm_class, (VOID *) cdc_ecm); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ECM_DEACTIVATE, cdc_ecm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, unregister this object. */ + UX_TRACE_OBJECT_UNREGISTER(cdc_ecm); + + /* Free the cdc_ecm control instance memory. */ + _ux_utility_memory_free(cdc_ecm); + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_endpoints_get.c new file mode 100644 index 0000000..cb5fcfb --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_endpoints_get.c @@ -0,0 +1,266 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_ecm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_ecm_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function distinguishes for either the Data or Control Class. */ +/* For the data class, we mount the bulk in and bulk out endpoints. */ +/* For the control class, we mount the optional interrupt endpoint. */ +/* */ +/* INPUT */ +/* */ +/* cdc_ecm Pointer to cdc_ecm class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_cdc_ecm_activate Activate cdc_ecm class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_ecm_endpoints_get(UX_HOST_CLASS_CDC_ECM *cdc_ecm) +{ + +UINT status; +UINT endpoint_index; +UX_ENDPOINT *endpoint; +UX_TRANSFER *transfer_request; +UX_INTERFACE *data_interface; + + + /* Get the endpoints from the data interface. */ + + /* Default data interface. */ + data_interface = cdc_ecm -> ux_host_class_cdc_ecm_interface_data; + + /* Some versions of cdc-ecm contain a default interface for data with 0 endpoints. Check if this the case and if so, + look for the next interface that has the 2 bulk endpoints. */ + + if (data_interface -> ux_interface_descriptor.bNumEndpoints == 0) + { + + /* We are in the case where the interface has the default set to 0 endpoints. */ + data_interface = data_interface -> ux_interface_next_interface; + + /* Check if invalid. */ + if (data_interface == UX_NULL || + data_interface -> ux_interface_descriptor.bInterfaceClass != UX_HOST_CLASS_CDC_DATA_CLASS || + data_interface -> ux_interface_descriptor.bAlternateSetting != 1) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, cdc_ecm -> ux_host_class_cdc_ecm_interface_data, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Descriptor is corrupted. */ + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* We have found the right alternate setting. Now we need to select it. */ + status = _ux_host_stack_interface_setting_select(data_interface); + + /* Check status. We don't continue if there is a problem with the selection. */ + if (status != UX_SUCCESS) + + /* Something went wrong. */ + return(status); + } + + /* Search the bulk OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < data_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get interface endpoint. */ + _ux_host_stack_interface_endpoint_get(data_interface, endpoint_index, &endpoint); + + /* Check if endpoint is bulk and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the OUT direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + + /* There is a callback function associated with the transfer request, so we need the class instance. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_class_instance = (VOID *) cdc_ecm; + + /* The transfer request has a callback function. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_completion_function = _ux_host_class_cdc_ecm_transmission_callback; + + /* We have found the bulk endpoint, save it. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_endpoint = endpoint; + + break; + } + } + + /* The bulk out endpoint is mandatory. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, cdc_ecm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search the bulk IN endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < data_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + _ux_host_stack_interface_endpoint_get(data_interface, endpoint_index, &endpoint); + + /* Check if endpoint is bulk and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* Set the class instance in the transfer request. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_class_instance = (VOID *) cdc_ecm; + + /* The transfer request has NO callback function. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_completion_function = UX_NULL; + + /* We have found the bulk endpoint, save it. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_endpoint = endpoint; + + break; + } + } + + /* The bulk in endpoint is mandatory. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, cdc_ecm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Now get the endpoints from the control interface. */ + + /* Search the Interrupt endpoint. It is NOT mandatory. */ + for (endpoint_index = 0; endpoint_index < cdc_ecm -> ux_host_class_cdc_ecm_interface_control -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + _ux_host_stack_interface_endpoint_get(cdc_ecm -> ux_host_class_cdc_ecm_interface_control, endpoint_index, &endpoint); + + /* Check if endpoint is Interrupt and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the interrupt endpoint, save it. */ + cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint = endpoint; + + /* The endpoint is correct, Fill in the transfer request with the length requested for this endpoint. */ + transfer_request = &cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_transfer_request; + transfer_request -> ux_transfer_request_requested_length = cdc_ecm -> ux_host_class_cdc_ecm_interrupt_endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + transfer_request -> ux_transfer_request_actual_length = 0; + + /* The direction is always IN for the CDC interrupt endpoint. */ + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN; + + /* There is a callback function associated with the transfer request, so we need the class instance. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) cdc_ecm; + + /* Interrupt transactions have a completion routine. */ + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_cdc_ecm_interrupt_notification; + + /* Obtain a buffer for this transaction. The buffer will always be reused. */ + transfer_request -> ux_transfer_request_data_pointer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + transfer_request -> ux_transfer_request_requested_length); + + /* If the endpoint is available and we have memory, we start the interrupt endpoint. */ + if (transfer_request -> ux_transfer_request_data_pointer == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We must return an error. */ + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + break; + } + } + + /* All endpoints have been mounted. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_entry.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_entry.c new file mode 100644 index 0000000..8ecfec9 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_entry.c @@ -0,0 +1,154 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_ecm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_ecm_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the cdc_ecm class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* cdc_ecm ethernet device on the bus or when the it is removed. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* command CDC ECM class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_cdc_ecm_activate Activate cdc_ecm class */ +/* _ux_host_class_cdc_ecm_deactivate Deactivate cdc_ecm class */ +/* */ +/* CALLED BY */ +/* */ +/* CDC ECM Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_ecm_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if(command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) + { + + /* We are in CSP mode. Check if CDC-ECM Control or Data. */ + if (((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_DATA_CLASS) && (command -> ux_host_class_command_subclass == 0)) || + ((command -> ux_host_class_command_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) && + (command -> ux_host_class_command_subclass == UX_HOST_CLASS_CDC_ECM_CONTROL_SUBCLASS))) + { + /* Check for IAD presence. */ + if ((command -> ux_host_class_command_iad_class == 0) && (command -> ux_host_class_command_iad_subclass == 0)) + + /* No IAD, we accept this class. */ + return(UX_SUCCESS); + + else + { + + if ((command -> ux_host_class_command_iad_class == UX_HOST_CLASS_CDC_CONTROL_CLASS) && + (command -> ux_host_class_command_iad_subclass == UX_HOST_CLASS_CDC_ECM_CONTROL_SUBCLASS)) + + /* There is an IAD and this is for CDC-ACM. */ + return(UX_SUCCESS); + + else + + /* The IAD does not match with CDC-ACM. */ + return(UX_NO_CLASS_MATCH); + } + } + + /* Not CDC-ECM control or data class. */ + return(UX_NO_CLASS_MATCH); + + } + + else + + /* No match. */ + return(UX_NO_CLASS_MATCH); + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_cdc_ecm_activate(command); + return(status); + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_cdc_ecm_deactivate(command); + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_interrupt_notification.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_interrupt_notification.c new file mode 100644 index 0000000..fb48507 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_interrupt_notification.c @@ -0,0 +1,174 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_ecm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_ecm_interrupt_notification PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the stack when an interrupt packet as */ +/* been received. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_cdc_ecm_interrupt_notification(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_CDC_ECM *cdc_ecm; +ULONG notification_type; +ULONG notification_value; + + + /* Get the control class instance for this transfer request. */ + cdc_ecm = (UX_HOST_CLASS_CDC_ECM *) transfer_request -> ux_transfer_request_class_instance; + + /* Check the state of the transfer. If there is an error, we do not proceed with this notification. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + + /* We do not proceed. */ + return; + + /* Check if the class is in shutdown. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_state == UX_HOST_CLASS_INSTANCE_SHUTDOWN) + + /* We do not proceed. */ + return; + + /* Increment the notification count. */ + cdc_ecm -> ux_host_class_cdc_ecm_notification_count++; + + /* Get the notification. */ + notification_type = (ULONG) *(transfer_request -> ux_transfer_request_data_pointer + UX_HOST_CLASS_CDC_ECM_NPF_NOTIFICATION_TYPE); + + /* And the value. */ + notification_value = (ULONG) *(transfer_request -> ux_transfer_request_data_pointer + UX_HOST_CLASS_CDC_ECM_NPF_VALUE); + + /* Check if the notification is a Network notification. */ + if (notification_type == UX_HOST_CLASS_CDC_ECM_NOTIFICATION_NETWORK_CONNECTION) + { + + /* Check the state of the link. */ + if (notification_value == UX_HOST_CLASS_CDC_ECM_NOTIFICATION_NETWORK_LINK_UP) + { + + /* Link is up. See if we know about that. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP && + cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_UP) + { + + /* Memorize the new link state. */ + cdc_ecm -> ux_host_class_cdc_ecm_link_state = UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_UP; + + /* We need to inform the cdc_ecm thread of this change. */ + _ux_utility_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); + } + } + else + { + + /* Link is down. See if we know about that. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN && + cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_DOWN) + { + + /* We need to abort any transfers on the bulk in endpoint. */ + + /* Make sure no one does any more transfers. */ + cdc_ecm -> ux_host_class_cdc_ecm_link_state = UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_DOWN; + + /* Now abort all transfers. It's possible we're executing right before the transfer + is armed. If this is the case, then the transfer will not be aborted if we do the abort right now; instead, + we should wait until after the transfer is armed. We must look at the CDC-ECM thread's state. */ + + /* Is it in the process of checking the link state and arming the transfer? */ + if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process == UX_TRUE) + { + + /* Yes. We must wait for it to finish arming the transfer. */ + + /* Let the CDC-ECM thread know we're waiting so it can wake us up. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish = UX_TRUE; + + /* Wait for the transfer to be armed, or possibly an error. The CDC-ECM thread will wake us up. */ + _ux_utility_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore, UX_WAIT_FOREVER); + + /* We're no longer waiting. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish = UX_FALSE; + } + + /* Now we can abort the transfer. */ + _ux_host_stack_transfer_request_abort(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_endpoint -> ux_endpoint_transfer_request); + + /* We need to inform the CDC-ECM thread of this change. */ + _ux_utility_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore); + } + } + } + + /* Reactivate the CDC_ECM interrupt pipe. */ + _ux_host_stack_transfer_request(transfer_request); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ECM_INTERRUPT_NOTIFICATION, cdc_ecm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_mac_address_get.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_mac_address_get.c new file mode 100644 index 0000000..d4dcfa4 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_mac_address_get.c @@ -0,0 +1,346 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_ecm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_ecm_mac_address_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to retrieve the MAC address from */ +/* the configuration descriptor. */ +/* */ +/* INPUT */ +/* */ +/* cdc_ecm Pointer to cdc_ecm class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_descriptor_parse Parse descriptors */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_cdc_ecm_activate CDC ECM class activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_ecm_mac_address_get(UX_HOST_CLASS_CDC_ECM *cdc_ecm) +{ + +UINT status; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UX_CONFIGURATION_DESCRIPTOR configuration_descriptor; +UCHAR *descriptor; +UCHAR *start_descriptor = UX_NULL; +ULONG configuration_index; +ULONG total_configuration_length; +UINT descriptor_length; +UINT descriptor_type; +UINT descriptor_subtype; +UX_HOST_CLASS_ECM_INTERFACE_DESCRIPTOR ecm_interface_descriptor; +UCHAR *mac_address_string; +ULONG string_index; +ULONG string_length; +UCHAR element_content; +UCHAR element_hexa_upper; +UCHAR element_hexa_lower; + + /* We now need to retrieve the MAC address of the node which is embedded in the ECM descriptor. + We will parse the entire configuration descriptor of the device and look for the ECM Ethernet Networking Functional Descriptor. */ + configuration_index = cdc_ecm -> ux_host_class_cdc_ecm_interface_data -> ux_interface_configuration -> ux_configuration_descriptor.bConfigurationValue -1; + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &cdc_ecm -> ux_host_class_cdc_ecm_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the descriptor. Since we do not know the size of the + descriptor, we first read the first bytes. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_CONFIGURATION_DESCRIPTOR_LENGTH); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Memorize the descriptor start address. */ + start_descriptor = descriptor; + + /* Create a transfer request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = UX_CONFIGURATION_DESCRIPTOR_LENGTH; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = (UX_CONFIGURATION_DESCRIPTOR_ITEM << 8) | configuration_index; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == UX_CONFIGURATION_DESCRIPTOR_LENGTH)) + { + + /* Parse the descriptor so that we can read the total length. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, (UCHAR *) &configuration_descriptor); + + /* We don't need this descriptor now. */ + _ux_utility_memory_free(descriptor); + + /* Reallocate the memory necessary for the reading the entire descriptor. */ + total_configuration_length = configuration_descriptor.wTotalLength; + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, total_configuration_length); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save this descriptor address. */ + start_descriptor = descriptor; + + /* Read the descriptor again with the correct length this time. */ + transfer_request -> ux_transfer_request_requested_length = total_configuration_length; + + /* Since the address of the descriptor may have changed, reprogram it. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == configuration_descriptor.wTotalLength)) + { + + /* The ECM descriptor is embedded within the configuration descriptor. We parse the + entire descriptor to locate the ECM functional descriptor portion. */ + while (total_configuration_length) + { + + /* Gather the length and type of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Check the type for an interface descriptor and the subtype for a ECM functional descriptor. */ + if ((descriptor_type == UX_HOST_CLASS_CDC_ECM_CS_INTERFACE) && (descriptor_subtype == UX_HOST_CLASS_CDC_ECM_FUNCTIONAL_DESCRIPTOR)) + { + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, + _ux_system_ecm_interface_descriptor_structure, + UX_HOST_CLASS_CDC_ECM_INTERFACE_DESCRIPTOR_ENTRIES, + (UCHAR *) &ecm_interface_descriptor); + + + /* Release the memory. */ + _ux_utility_memory_free(start_descriptor); + + /* We now have the ECM functional descriptor in memory. We can retrieve the index of the iMACAddress + which we need for NetX. */ + + /* Allocate memory for the MAC address. */ + mac_address_string = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_CDC_ECM_MAC_ADDRESS_STRING_LENGTH); + + /* Check memory allocation. */ + if (mac_address_string == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Create a transfer request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = mac_address_string; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_CDC_ECM_MAC_ADDRESS_STRING_LENGTH; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = (UX_STRING_DESCRIPTOR_ITEM << 8) | ecm_interface_descriptor.iMACAddress; + transfer_request -> ux_transfer_request_index = 0x0409; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer. */ + if (status == UX_SUCCESS) + { + + /* Translate from Unicode to string. Length is in the first byte. We must take away 2 from it + and divide by 2 to find the right asciiz length. */ + string_length = (ULONG) *mac_address_string; + + /* Check the length of the mac address Unicode string. */ + if (string_length > 26) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* Return error. */ + status = UX_DESCRIPTOR_CORRUPTED; + } + else + { + + /* No error in length, decode the string. */ + string_length -=2; + string_length = string_length/2; + + /* Now we have a string of 12 hexa ASCII digits to be translated into 6 hexa digit bytes. + and copy into the node ID. */ + for (string_index = 0; string_index < string_length; string_index++) + { + + /* Get the upper element from the ASCII string. */ + element_content = *(mac_address_string + (string_index * 2) + 2); + + /* We have a valid element content. Turn it into a hexa decimal value. Note + that only hex digits are allowed. */ + if (element_content <= '9') + + /* We have a digit. */ + element_hexa_upper = (UCHAR)(element_content - '0'); + + else + { + /* We have a 'A' to 'F' or 'a' to 'f' value. */ + if (element_content >= 'a') + + /* We have a 'a' to 'f' char. */ + element_hexa_upper = (UCHAR)(element_content - 'a' + 10); + + else + + /* We have a 'A' to 'F' char. */ + element_hexa_upper = (UCHAR)(element_content - 'A' + 10); + + } + + /* Get the lower element from the ASCII string. */ + element_content = *(mac_address_string + ((string_index + 1) * 2) + 2); + + /* We have a valid element content. Turn it into a hexa decimal value. Note + that only hex digits are allowed. */ + if (element_content <= '9') + + /* We have a digit. */ + element_hexa_lower = (UCHAR)(element_content - '0'); + + else + { + /* We have a 'A' to 'F' or 'a' to 'f' value. */ + if (element_content >= 'a') + + /* We have a 'a' to 'f' char. */ + element_hexa_lower = (UCHAR)(element_content - 'a' + 10); + + else + + /* We have a 'A' to 'F' char. */ + element_hexa_lower = (UCHAR)(element_content - 'A' + 10); + + } + + /* Assemble the byte from the 2 nibbles and store it into the node_id. */ + *(cdc_ecm -> ux_host_class_cdc_ecm_node_id + string_index / 2) = (UCHAR)(element_hexa_upper << 4 | element_hexa_lower); + + /* Skip the lower nibble. */ + string_index++; + + } + + /* Operation was successful ! */ + status = UX_SUCCESS; + } + } + else + { + + /* We have a bad MAC address string. Do not proceed. */ + status = UX_ERROR; + } + + /* Free the MAC address string. */ + _ux_utility_memory_free(mac_address_string); + + /* Return completion status. */ + return(status); + } + else + { + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_configuration_length -= descriptor_length; + } + } + } + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, &configuration_descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Release the memory. */ + _ux_utility_memory_free(start_descriptor); + + /* Return an error. */ + return(UX_DESCRIPTOR_CORRUPTED); + +} + + + + + + + + + + + + + + diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_thread.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_thread.c new file mode 100644 index 0000000..78aab54 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_thread.c @@ -0,0 +1,244 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_ecm.h" +#include "ux_host_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_ecm_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This is the CDC ECM thread that monitors the link change flag, */ +/* receives data from the device, and passes the data to the NetX-USB */ +/* broker. */ +/* */ +/* INPUT */ +/* */ +/* cdc_ecm CDC ECM instance */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_cdc_ecm_transmit_queue_clean */ +/* Clean transmit queue */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_utility_short_get_big_endian Get 16-bit big endian */ +/* _ux_network_driver_link_up Set state link up */ +/* _ux_network_driver_link_down Set state link down */ +/* _ux_network_driver_packet_received Process received packet */ +/* nx_packet_allocate Allocate NetX packet */ +/* nx_packet_release Free NetX packet */ +/* */ +/* CALLED BY */ +/* */ +/* CDC ECM class initialization */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_cdc_ecm_thread(ULONG parameter) +{ + +UX_HOST_CLASS_CDC_ECM *cdc_ecm; +UX_TRANSFER *transfer_request; +NX_PACKET *packet; +ULONG ip_given_length; +UINT status; + + /* Cast the parameter passed in the thread into the cdc_ecm pointer. */ + UX_THREAD_EXTENSION_PTR_GET(cdc_ecm, UX_HOST_CLASS_CDC_ECM, parameter) + + /* Loop forever waiting for changes signaled through the semaphore. */ + while (1) + { + + /* Wait for the semaphore to be put by the cdc_ecm interrupt event. */ + _ux_utility_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_interrupt_notification_semaphore, UX_WAIT_FOREVER); + + /* Check the link state. It is either pending up or down. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_link_state == UX_HOST_CLASS_CDC_ECM_LINK_STATE_PENDING_UP) + { + + /* Now the link is up. */ + cdc_ecm -> ux_host_class_cdc_ecm_link_state = UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP; + + /* Communicate the state with the network driver. */ + _ux_network_driver_link_up(cdc_ecm -> ux_host_class_cdc_ecm_network_handle); + + /* As long as we are connected, configured and link up ... do some work.... */ + while ((cdc_ecm -> ux_host_class_cdc_ecm_link_state == UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP) && + (cdc_ecm -> ux_host_class_cdc_ecm_device -> ux_device_state == UX_DEVICE_CONFIGURED)) + { + + /* We can accept reception. Get a NX Packet. */ + status = nx_packet_allocate(&cdc_ecm -> ux_host_class_cdc_ecm_packet_pool, &packet, + NX_RECEIVE_PACKET, MS_TO_TICK(UX_HOST_CLASS_CDC_ECM_PACKET_POOL_WAIT)); + + if (status == NX_SUCCESS) + { + + /* Adjust the prepend pointer to take into account the non 3 bit alignment of the ethernet header. */ + packet -> nx_packet_prepend_ptr += sizeof(USHORT); + + /* We have a packet. Link this packet to the reception transfer request on the bulk in endpoint. */ + transfer_request = &cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Set the data pointer. */ + transfer_request -> ux_transfer_request_data_pointer = packet -> nx_packet_prepend_ptr; + + /* And length. */ + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_CDC_ECM_NX_PAYLOAD_SIZE; + transfer_request -> ux_transfer_request_actual_length = 0; + + /* Store the packet that owns this transaction. */ + transfer_request -> ux_transfer_request_user_specific = packet; + + /* Reset the queue pointer of this packet. */ + packet -> nx_packet_queue_next = UX_NULL; + + /* We're arming the transfer now. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process = UX_TRUE; + + /* Is the link up? */ + if (cdc_ecm -> ux_host_class_cdc_ecm_link_state == UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP) + { + + /* Ask USB to schedule a reception. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Signal that we are done arming and resume waiting thread if necessary. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process = UX_FALSE; + if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish == UX_TRUE) + _ux_utility_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); + + /* Check if the transaction was armed successfully. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, TX_WAIT_FOREVER); + + /* Check the transfer status. If there is a transport error, we ignore the packet + and restart it. */ + if (transfer_request -> ux_transfer_request_completion_code == UX_SUCCESS) + { + + /* Get the packet length. */ + packet -> nx_packet_length = transfer_request -> ux_transfer_request_actual_length; + + /* Adjust the prepend, length, and append fields. */ + packet -> nx_packet_append_ptr = + packet->nx_packet_prepend_ptr + transfer_request -> ux_transfer_request_actual_length; + + /* Calculate the accurate packet length from ip header */ + if ((*(packet -> nx_packet_prepend_ptr + 12) == 0x08) && + (*(packet -> nx_packet_prepend_ptr + 13) == 0)) + { + + ip_given_length = _ux_utility_short_get_big_endian(packet -> nx_packet_prepend_ptr + 16) + UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE; + packet->nx_packet_length = ip_given_length ; + packet->nx_packet_append_ptr = packet->nx_packet_prepend_ptr + ip_given_length; + } + + /* Send that packet to the NetX USB broker. */ + _ux_network_driver_packet_received(cdc_ecm -> ux_host_class_cdc_ecm_network_handle, packet); + } + else + { + + /* Free the packet that was not successfully received. */ + nx_packet_release(packet); + } + } + else + { + + /* Error arming transfer. */ + + /* Release packet. */ + nx_packet_release(packet); + } + } + else + { + + /* Link is down. */ + + /* Signal that we are done arming and resume waiting thread if necessary. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_check_and_arm_in_process = UX_FALSE; + if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish == UX_TRUE) + _ux_utility_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_in_transfer_waiting_for_check_and_arm_to_finish_semaphore); + + /* Release packet. */ + nx_packet_release(packet); + } + } + else + { + + /* Packet allocation timed out. Note that the timeout value is + configurable. */ + + /* Error trap. No need for trace, since NetX does it. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + } + } + } + else + { + + /* The link state is pending down. We need to free the xmit queue. */ + _ux_host_class_cdc_ecm_transmit_queue_clean(cdc_ecm); + + /* Link state can now be set to down. */ + + /* Notify the network driver. */ + _ux_network_driver_link_down(cdc_ecm -> ux_host_class_cdc_ecm_network_handle); + + /* Set the link state. */ + cdc_ecm -> ux_host_class_cdc_ecm_link_state = UX_HOST_CLASS_CDC_ECM_LINK_STATE_DOWN; + } + } +} diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmission_callback.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmission_callback.c new file mode 100644 index 0000000..9802e33 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmission_callback.c @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC-ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_ecm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_ecm_transmission_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the callback from the USBX transfer functions, */ +/* it is called when a full or partial transfer has been done for a */ +/* bulk out transfer. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* nx_packet_transmit_release Release NetX packet */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_cdc_ecm_transmission_callback(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_CDC_ECM *cdc_ecm; +NX_PACKET *current_packet; +NX_PACKET *next_packet; +UCHAR *packet_header; + + /* Get the data and control class instances for this transfer request. */ + cdc_ecm = (UX_HOST_CLASS_CDC_ECM *) transfer_request -> ux_transfer_request_class_instance; + + /* Is the link not up, or the class is shutting down? */ + if (cdc_ecm -> ux_host_class_cdc_ecm_link_state != UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP || + cdc_ecm -> ux_host_class_cdc_ecm_state == UX_HOST_CLASS_INSTANCE_SHUTDOWN) + + /* The CDC-ECM thread or deactivation routine is in the process of freeing + the queue. Just return so we are not simultaneously accessing it. */ + return; + + /* Get the packet associated with this transfer. */ + current_packet = cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_head; + + /* Do a sanity check on the packet. */ + if (current_packet == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FATAL_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_INTERFACE_HANDLE_UNKNOWN, cdc_ecm, 0, 0, UX_FATAL_ERROR, 0, 0) + + /* Something went terribly wrong. Do not proceed. */ + return; + } + + /* Check the state of the transfer. */ + if (transfer_request -> ux_transfer_request_completion_code == UX_SUCCESS) + { + + /* Get the next packet associated with the first packet. */ + next_packet = current_packet -> nx_packet_queue_next; + + /* Set the next packet (or a NULL value) as the head of the xmit queue. */ + cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_head = next_packet; + + /* If there is nothing else or if the link is down no need to rearm a packet. */ + if (next_packet != UX_NULL) + { + + /* Load the address of the current packet header at the physical header. */ + packet_header = next_packet -> nx_packet_prepend_ptr; + + /* Prepare the values for this new transmission. */ + transfer_request -> ux_transfer_request_data_pointer = packet_header; + transfer_request -> ux_transfer_request_requested_length = next_packet -> nx_packet_length; + + /* Store the packet that owns this transaction. */ + transfer_request -> ux_transfer_request_user_specific = next_packet; + + /* If error log is enabled, insert this message into the log buffer. */ + UX_DEBUG_LOG("_ux_host_class_cdc_ecm_transmission_callback", "Sending packet", next_packet, next_packet, _ux_system -> ux_system_mutex.tx_mutex_suspended_count) + + /* If there is an error, the system will hang up. Not much we can do to + fix this. */ + _ux_host_stack_transfer_request(transfer_request); + } + + /* If error log is enabled, insert this message into the log buffer. */ + UX_DEBUG_LOG("_ux_host_class_cdc_ecm_transmission_callback", "Freeing transmitted packet", 0, transfer_request, current_packet) + + /* Free the packet that was just sent. First do some housekeeping. */ + current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE; + current_packet -> nx_packet_length = current_packet -> nx_packet_length - UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE; + + /* And ask Netx to release it. */ + nx_packet_transmit_release(current_packet); + } + else + { + + /* The transfer failed. Retry it. Note that this can't be a transfer + abort, because otherwise the link is either down or the class is in + shutdown, both of which are checked for at the beginning. */ + _ux_host_stack_transfer_request(transfer_request); + } + + /* There is no status to be reported back to the stack. */ + return; +} diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmit_queue_clean.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmit_queue_clean.c new file mode 100644 index 0000000..843f7be --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_transmit_queue_clean.c @@ -0,0 +1,140 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC_ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_ecm.h" +#include "ux_host_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_ecm_transmit_queue_clean PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cleans the transmit queue. */ +/* */ +/* INPUT */ +/* */ +/* cdc_ecm CDC ECM instance */ +/* */ +/* OUTPUT */ +/* */ +/* No return value */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_semaphore_get Get bulk out semaphore */ +/* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ +/* nx_packet_transmit_release Release NetX packet */ +/* */ +/* CALLED BY */ +/* */ +/* CDC ECM thread and deactivation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_cdc_ecm_transmit_queue_clean(UX_HOST_CLASS_CDC_ECM *cdc_ecm) +{ + +TX_INTERRUPT_SAVE_AREA + +NX_PACKET *current_packet; +NX_PACKET *next_packet; + + /* Disable interrupts while we check the write in process flag and + set our own state. */ + TX_DISABLE + + /* Is there a write in process? */ + if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_check_and_arm_in_process == UX_TRUE) + { + + /* Wait for writes to complete. Note that once these writes complete, + no more should occur since the link state is pending down. */ + + /* Mark this thread as suspended so it will be woken up. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish = UX_TRUE; + + /* Restore interrupts while we wait. */ + TX_RESTORE + + /* Wait for write function to resume us. */ + _ux_utility_semaphore_get(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore, UX_WAIT_FOREVER); + + /* We're done waiting. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish = UX_FALSE; + } + else + { + + /* No writes are in process. Restore interrupts and go on to free + the xmit queue. */ + TX_RESTORE + } + + /* Abort transfers on the bulk out endpoint. Note we need to do this + before accessing the queue since the transmission callback might + modify it. */ + _ux_host_stack_transfer_request_abort(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_endpoint -> ux_endpoint_transfer_request); + + /* Get the first packet. */ + current_packet = cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_head; + + /* We need to free the packets that will not be sent. */ + while (current_packet != UX_NULL) + { + + /* We must get the next packet before releasing the current packet + because nxe_packet_transmit_release sets the pointer we pass + to null. */ + next_packet = current_packet -> nx_packet_queue_next; + + /* Free the packet. First do some housekeeping. */ + current_packet -> nx_packet_prepend_ptr = current_packet -> nx_packet_prepend_ptr + UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE; + current_packet -> nx_packet_length = current_packet -> nx_packet_length - UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE; + + /* And ask Netx to release it. */ + nx_packet_transmit_release(current_packet); + + /* Next packet becomes the current one. */ + current_packet = next_packet; + } + + /* Clear the queue. */ + cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_head = UX_NULL; +} diff --git a/common/usbx_host_classes/src/ux_host_class_cdc_ecm_write.c b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_write.c new file mode 100644 index 0000000..8a8f708 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_cdc_ecm_write.c @@ -0,0 +1,216 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** CDC ECM Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_cdc_ecm.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_ecm_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the cdc_ecm interface. The call is */ +/* non-blocking and queues the packet if there is an on-going write. */ +/* */ +/* INPUT */ +/* */ +/* cdc_ecm Pointer to cdc_ecm class */ +/* packet Packet to write or queue */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* nx_packet_transmit_release Release NetX packet */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_cdc_ecm_write(VOID *cdc_ecm_class, NX_PACKET *packet) +{ + +TX_INTERRUPT_SAVE_AREA + +UX_TRANSFER *transfer_request; +UINT status; +UCHAR *packet_header; +UX_HOST_CLASS_CDC_ECM *cdc_ecm; + + /* Get the instance. */ + cdc_ecm = (UX_HOST_CLASS_CDC_ECM *) cdc_ecm_class; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_CDC_ECM_WRITE, cdc_ecm, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We're arming transfer now. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_check_and_arm_in_process = UX_TRUE; + + /* We need to disable interrupts here because we need to make sure that if the xmit + queue is non-null, it remains non-null until we have queued the packet. + Note that we do not have to worry about the case where the queue is null, + because we are the only ones that can change it from null to non-null. */ + TX_DISABLE + + /* Ensure the instance is valid. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, cdc_ecm, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Are we in a valid state? */ + if (cdc_ecm -> ux_host_class_cdc_ecm_link_state == UX_HOST_CLASS_CDC_ECM_LINK_STATE_UP) + { + + /* Check the queue. See if there is something that is being sent. */ + if (cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_head == UX_NULL) + { + + /* Reset the queue pointer of this packet. */ + packet -> nx_packet_queue_next = UX_NULL; + + /* Memorize this packet at the beginning of the queue. */ + cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_head = packet; + cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_tail = packet; + + /* Restore interrupts. */ + TX_RESTORE + + /* Now we need to arm the transfer. */ + + /* Get the pointer to the bulk out endpoint transfer request. */ + transfer_request = &cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Load the address of the current packet header at the physical header. */ + packet_header = packet -> nx_packet_prepend_ptr; + + /* Setup the transaction parameters. */ + transfer_request -> ux_transfer_request_data_pointer = packet_header; + transfer_request -> ux_transfer_request_requested_length = packet -> nx_packet_length; + + /* Store the packet that owns this transaction. */ + transfer_request -> ux_transfer_request_user_specific = packet; + + /* Arm the transfer request. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Did we successfully arm the transfer? */ + if (status != UX_SUCCESS) + { + + /* Clear the queue. No need to clear the tail. */ + cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_head = UX_NULL; + + /* We cleared the queue, so we must free the packet. First + we need to clean it before passing it to NetX. */ + packet -> nx_packet_prepend_ptr = packet -> nx_packet_prepend_ptr + UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE; + packet -> nx_packet_length = packet -> nx_packet_length - UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE; + + /* And ask Netx to release it. */ + nx_packet_transmit_release(packet); + + /* Could not arm this transfer. */ + status = UX_ERROR; + } + } + else + { + + /* The packet to be sent is the last in the chain. */ + packet -> nx_packet_queue_next = NX_NULL; + + /* Memorize the packet to be sent. */ + cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_tail -> nx_packet_queue_next = packet; + + /* Set the tail. */ + cdc_ecm -> ux_host_class_cdc_ecm_xmit_queue_tail = packet; + + /* Restore interrupts. */ + TX_RESTORE + + /* Successfully added to queue. */ + status = UX_SUCCESS; + } + } + else + { + + /* Link was down. */ + + /* Restore interrupts. */ + TX_RESTORE + + /* Release the packet. */ + packet -> nx_packet_prepend_ptr = packet -> nx_packet_prepend_ptr + UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE; + packet -> nx_packet_length = packet -> nx_packet_length - UX_HOST_CLASS_CDC_ECM_ETHERNET_SIZE; + nx_packet_transmit_release(packet); + + /* Report error to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_CDC_ECM_LINK_STATE_DOWN_ERROR); + + /* Return error. */ + status = UX_ERROR; + } + + /* Signal that we are done arming and resume waiting thread if necessary. */ + cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_check_and_arm_in_process = UX_FALSE; + if (cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish == UX_TRUE) + _ux_utility_semaphore_put(&cdc_ecm -> ux_host_class_cdc_ecm_bulk_out_transfer_waiting_for_check_and_arm_to_finish_semaphore); + + /* We are done here. */ + return(status); +} diff --git a/common/usbx_host_classes/src/ux_host_class_gser_activate.c b/common/usbx_host_classes/src/ux_host_class_gser_activate.c new file mode 100644 index 0000000..fa49e51 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_activate.c @@ -0,0 +1,149 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to activate the class. */ +/* */ +/* INPUT */ +/* */ +/* command Dpump class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_gser_configure Configure gser class */ +/* _ux_host_class_gser_endpoints_get Get endpoints of gser */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_gser_entry Entry of gser class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_gser_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_DEVICE *device; +UX_HOST_CLASS_GSER *gser; +UINT status; + + + /* The Generic Modem class is always activated by the device descriptor. */ + device = (UX_DEVICE *) command -> ux_host_class_command_container; + + /* Obtain memory for this class instance. */ + gser = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS_GSER)); + if (gser == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance. */ + gser -> ux_host_class_gser_class = command -> ux_host_class_command_class_ptr; + + /* Store the device container into the gser class instance. */ + gser -> ux_host_class_gser_device = device; + + /* Store the instance in the device container, this is for the USBX stack + when it needs to invoke the class for deactivation. */ + device -> ux_device_class_instance = (VOID *) gser; + + /* Create this class instance. */ + status = _ux_host_stack_class_instance_create(gser -> ux_host_class_gser_class, (VOID *) gser); + + /* Configure the gser class. */ + status = _ux_host_class_gser_configure(gser); + + /* Get the gser endpoint(s). We will need to search for Bulk Out and Bulk In endpoints on each interface . */ + if (status == UX_SUCCESS) + status = _ux_host_class_gser_endpoints_get(gser); + + /* Success things. */ + if (status == UX_SUCCESS) + { + + /* Mark the gser as live now. */ + gser -> ux_host_class_gser_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, gser -> ux_host_class_gser_class, (VOID *) gser); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_ACTIVATE, gser, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, gser, 0, 0, 0) + + /* Return success. */ + return(UX_SUCCESS); + } + + /* Destroy class instance. */ + _ux_host_stack_class_instance_destroy(gser -> ux_host_class_gser_class, (VOID *) gser); + + /* Clear the instance in the device container. */ + device -> ux_device_class_instance = UX_NULL; + + /* Free instance memory. */ + _ux_utility_memory_free(gser); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_gser_command.c b/common/usbx_host_classes/src/ux_host_class_gser_command.c new file mode 100644 index 0000000..6146204 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_command.c @@ -0,0 +1,163 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_command PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will send a command to the ACM device. The command */ +/* can be one of the following : */ +/* SET_CONTROL */ +/* SET_LINE */ +/* SEND_BREAK */ +/* */ +/* */ +/* INPUT */ +/* */ +/* acm Pointer to acm class */ +/* command command value */ +/* value value to be sent in the */ +/* command request */ +/* data_buffer buffer to be sent */ +/* data_length length of the buffer to send */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_gser_command(UX_HOST_CLASS_GSER *gser, ULONG interface_index, ULONG command, + ULONG value, UCHAR *data_buffer, ULONG data_length) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +ULONG request_direction; + + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &gser -> ux_host_class_gser_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Check the direction of the command. */ + switch (command) + { + + case UX_HOST_CLASS_GSER_REQ_SEND_ENCAPSULATED_COMMAND : + case UX_HOST_CLASS_GSER_REQ_SET_COMM_FEATURE : + case UX_HOST_CLASS_GSER_REQ_CLEAR_COMM_FEATURE : + case UX_HOST_CLASS_GSER_REQ_SET_AUX_LINE_STATE : + case UX_HOST_CLASS_GSER_REQ_SET_HOOK_STATE : + case UX_HOST_CLASS_GSER_REQ_PULSE_SETUP : + case UX_HOST_CLASS_GSER_REQ_SEND_PULSE : + case UX_HOST_CLASS_GSER_REQ_SET_PUSLE_TIME : + case UX_HOST_CLASS_GSER_REQ_RING_AUX_JACK : + case UX_HOST_CLASS_GSER_REQ_SET_LINE_CODING : + case UX_HOST_CLASS_GSER_REQ_SET_LINE_STATE : + case UX_HOST_CLASS_GSER_REQ_SEND_BREAK : + case UX_HOST_CLASS_GSER_REQ_SET_RINGER_PARMS : + case UX_HOST_CLASS_GSER_REQ_SET_OPERATION_PARMS : + case UX_HOST_CLASS_GSER_REQ_SET_LINE_PARMS : + + /* Direction is out */ + request_direction = UX_REQUEST_OUT; + break; + + + case UX_HOST_CLASS_GSER_REQ_GET_ENCAPSULATED_COMMAND : + case UX_HOST_CLASS_GSER_REQ_GET_COMM_FEATURE : + case UX_HOST_CLASS_GSER_REQ_GET_LINE_CODING : + case UX_HOST_CLASS_GSER_REQ_GET_RINGER_PARMS : + case UX_HOST_CLASS_GSER_REQ_GET_OPERATION_PARMS : + case UX_HOST_CLASS_GSER_REQ_GET_LINE_PARMS : + + /* Direction is in */ + request_direction = UX_REQUEST_IN; + break; + + + default : + + return(UX_ERROR); + + } + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&gser -> ux_host_class_gser_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + + /* Something went wrong. */ + return(status); + + /* Create a transfer_request for the request. */ + transfer_request -> ux_transfer_request_data_pointer = data_buffer; + transfer_request -> ux_transfer_request_requested_length = data_length; + transfer_request -> ux_transfer_request_function = command; + transfer_request -> ux_transfer_request_type = request_direction | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = value; + transfer_request -> ux_transfer_request_index = gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_interface->ux_interface_descriptor.bInterfaceNumber; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_gser_configure.c b/common/usbx_host_classes/src/ux_host_class_gser_configure.c new file mode 100644 index 0000000..d0ab93b --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_configure.c @@ -0,0 +1,164 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to the */ +/* gser. Once the gser is configured, its interface will be */ +/* activated. The bulk endpoints enumerated(1 IN, 1 OUT ). */ +/* */ +/* INPUT */ +/* */ +/* gser Pointer to gser class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get Get interface */ +/* _ux_host_stack_device_configuration_get Get configuration */ +/* _ux_host_stack_device_configuration_select Select configuration */ +/* _ux_utility_semaphore_create Create semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_gser_activate gser class activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_gser_configure(UX_HOST_CLASS_GSER *gser) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_DEVICE *parent_device; +ULONG interface_index; + + /* If the device has been configured already, we don't need to do it + again. */ + if (gser -> ux_host_class_gser_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* A gser normally has one configuration. So retrieve the 1st configuration + only. */ + status = _ux_host_stack_device_configuration_get(gser -> ux_host_class_gser_device, 0, &configuration); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, gser -> ux_host_class_gser_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check the gser power source and check the parent power source for + incompatible connections. */ + if (gser -> ux_host_class_gser_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* Get parent device pointer. */ + parent_device = gser -> ux_host_class_gser_device -> ux_device_parent; + + /* If the device is NULL, the parent is the root gser and we don't have to worry + if the parent is not the root gser, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, gser, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration. */ + status = _ux_host_stack_device_configuration_select(configuration); + if (status != UX_SUCCESS) + return(status); + + /* If the operation went well, the gser default alternate setting for the gser interface is + active. We have to scan all interfaces and attach them. Each interface has an semaphore as well for protection. */ + for (interface_index = 0; interface_index < UX_HOST_CLASS_GSER_INTERFACE_NUMBER; interface_index++) + { + + /* Get that interface. */ + status = _ux_host_stack_configuration_interface_get(configuration, interface_index, 0, &gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_interface); + + /* Should not fail. But do a sanity check. */ + if (status == UX_SUCCESS) + { + + /* Store the instance in the interface container, this is for the USB stack + when it needs to invoke the class. */ + gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_interface -> ux_interface_class_instance = (VOID *) gser; + + /* Store the class container in the interface. The device has the correct class, duplicate it to the + interface. */ + gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_interface -> ux_interface_class = gser -> ux_host_class_gser_device -> ux_device_class ; + + /* Create the semaphore to protect 2 threads from accessing the same gser instance. */ + status = _ux_utility_semaphore_create(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore, "ux_host_class_gser_semaphore", 1); + + /* Check status. */ + if (status != UX_SUCCESS) + return(UX_SEMAPHORE_ERROR); + + } + } + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_gser_deactivate.c b/common/usbx_host_classes/src/ux_host_class_gser_deactivate.c new file mode 100644 index 0000000..4ecdfb8 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_deactivate.c @@ -0,0 +1,130 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the gser has been */ +/* removed from the bus either directly or indirectly. The bulk in\out */ +/* pipes will be destroyed and the instanced removed. */ +/* */ +/* INPUT */ +/* */ +/* command Swar class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort endpoint transfer */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_utility_thread_schedule_other Schedule other threads */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_gser_entry Entry of gser class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_gser_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_GSER *gser; +ULONG interface_index; + + /* Get the instance for this class. */ + gser = (UX_HOST_CLASS_GSER *) command -> ux_host_class_command_instance; + + /* The gser class is being shut down. */ + gser -> ux_host_class_gser_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + for (interface_index = 0; interface_index < UX_HOST_CLASS_GSER_INTERFACE_NUMBER; interface_index++) + { + + /* We need to abort transactions on the bulk Out pipes. */ + _ux_host_stack_endpoint_transfer_abort(gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_out_endpoint); + + /* We need to abort transactions on the bulk In pipes. */ + _ux_host_stack_endpoint_transfer_abort(gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_in_endpoint); + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Destroy the semaphore. */ + _ux_utility_semaphore_delete(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + + } + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(gser -> ux_host_class_gser_class, (VOID *) gser); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, gser -> ux_host_class_gser_class, (VOID *) gser); + } + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_DEACTIVATE, gser, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(gser); + + /* Free the gser instance memory. */ + _ux_utility_memory_free(gser); + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_gser_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_gser_endpoints_get.c new file mode 100644 index 0000000..ca59f94 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_endpoints_get.c @@ -0,0 +1,164 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function search for the handle of the bulk out and bulk in */ +/* endpoints. The Generic Serial USB device has multiple interfaces. */ +/* */ +/* INPUT */ +/* */ +/* gser Pointer to gser class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_gser_activate Activate gser class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_gser_endpoints_get(UX_HOST_CLASS_GSER *gser) +{ + +UINT status; +UX_ENDPOINT *endpoint; +ULONG endpoint_index; +ULONG interface_index; + + /* Search the endpoints on all interfaces. */ + for (interface_index = 0; interface_index < UX_HOST_CLASS_GSER_INTERFACE_NUMBER; interface_index++) + { + + /* Search the bulk OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get interface endpoint. */ + status = _ux_host_stack_interface_endpoint_get(gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the OUT direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + + /* We have found the bulk endpoint, save it. */ + gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_out_endpoint = endpoint; + break; + } + } + } + + /* The bulk out endpoint is mandatory. */ + if (gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_out_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, gser, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search the bulk IN endpoint. It is attached to the interface container. */ + + for (endpoint_index = 0; endpoint_index < gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + status = _ux_host_stack_interface_endpoint_get(gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the bulk endpoint, save it. */ + gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_in_endpoint = endpoint; + break; + } + } + } + + /* The bulk in endpoint is mandatory. */ + if (gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_in_endpoint == UX_NULL) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, gser, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + } + /* All endpoints have been mounted. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_gser_entry.c b/common/usbx_host_classes/src/ux_host_class_gser_entry.c new file mode 100644 index 0000000..122c9ff --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_entry.c @@ -0,0 +1,120 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the gser class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* gser on the bus or when the USB gser is removed. */ +/* */ +/* INPUT */ +/* */ +/* command gser class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_gser_activate Activate gser class */ +/* _ux_host_class_gser_deactivate Deactivate gser class */ +/* */ +/* CALLED BY */ +/* */ +/* Data pump Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_gser_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if(((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_PIDVID) && + (command -> ux_host_class_command_pid == UX_HOST_CLASS_GSER_PRODUCT_ID) && + (command -> ux_host_class_command_vid == UX_HOST_CLASS_GSER_VENDOR_ID ))) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_gser_activate(command); + return(status); + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_gser_deactivate(command); + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_gser_ioctl.c b/common/usbx_host_classes/src/ux_host_class_gser_ioctl.c new file mode 100644 index 0000000..eff1cd7 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_ioctl.c @@ -0,0 +1,287 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_ioctl PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the ioctl entry point for the application to */ +/* configure the ACM device. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* acm Pointer to acm class */ +/* ioctl_function ioctl function */ +/* parameter pointer to structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_gser_command Send command to acm device */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort transfer */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_long_put Put 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_gser_ioctl(UX_HOST_CLASS_GSER *gser, ULONG interface_index, ULONG ioctl_function, + VOID *parameter) +{ + +UINT status; +UCHAR *data_buffer; +UX_HOST_CLASS_GSER_LINE_CODING *line_coding; +UX_HOST_CLASS_GSER_LINE_STATE *line_state; +VOID (*callback_function) (struct UX_HOST_CLASS_GSER_STRUCT *, ULONG, ULONG ); +ULONG value; + + /* Ensure the instance is valid. */ + if (gser -> ux_host_class_gser_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, gser, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* The command request will tell us we need to do here. */ + switch (ioctl_function) + { + + case UX_HOST_CLASS_GSER_IOCTL_SET_LINE_CODING: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_SET_LINE_CODING, gser, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Allocate some cache safe memory for the control command. */ + data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_GSER_LINE_CODING_LENGTH); + + /* Check if error. Return with error if no memory could be allocated. */ + if (data_buffer == UX_NULL) + + /* Do not proceed. Set error code. */ + status = UX_MEMORY_INSUFFICIENT; + else + { + + /* Build the buffer from the calling parameter. Cast the calling parameter. */ + line_coding = (UX_HOST_CLASS_GSER_LINE_CODING *) parameter; + + /* Put the data rate. */ + _ux_utility_long_put(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_RATE, + line_coding -> ux_host_class_gser_line_coding_dter); + + /* Then the stop bit. */ + *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_STOP_BIT) = + (UCHAR) line_coding -> ux_host_class_gser_line_coding_stop_bit; + + /* Then the parity. */ + *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_PARITY) = + (UCHAR) line_coding -> ux_host_class_gser_line_coding_parity; + + /* Finally the data bits. */ + *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_DATA_BIT) = + (UCHAR) line_coding -> ux_host_class_gser_line_coding_data_bits; + + /* Send the command to the device. */ + status = _ux_host_class_gser_command(gser, interface_index, UX_HOST_CLASS_GSER_REQ_SET_LINE_CODING, + 0, data_buffer, UX_HOST_CLASS_GSER_LINE_CODING_LENGTH); + + /* We free the resources allocated no matter what. */ + _ux_utility_memory_free(data_buffer); + } + break; + + case UX_HOST_CLASS_GSER_IOCTL_GET_LINE_CODING: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_GET_LINE_CODING, gser, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Allocate some cache safe memory for the control command. */ + data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_GSER_LINE_CODING_LENGTH); + + /* Check if error. Return with error if no memory could be allocated. */ + if (data_buffer == UX_NULL) + + /* Do not proceed. Set error code. */ + status = UX_MEMORY_INSUFFICIENT; + else + { + + /* Send the command to the device. */ + status = _ux_host_class_gser_command(gser, interface_index, UX_HOST_CLASS_GSER_REQ_GET_LINE_CODING, + 0, data_buffer, UX_HOST_CLASS_GSER_LINE_CODING_LENGTH); + + /* Fill in the calling buffer if the result is successful. */ + if (status == UX_SUCCESS) + { + + /* Build the buffer from the calling parameter. Cast the calling parameter. */ + line_coding = (UX_HOST_CLASS_GSER_LINE_CODING *) parameter; + + /* Get the data rate. */ + line_coding -> ux_host_class_gser_line_coding_dter = _ux_utility_long_get(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_RATE); + + /* Then the stop bit. */ + line_coding -> ux_host_class_gser_line_coding_stop_bit = + (ULONG) *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_STOP_BIT); + + /* Then the parity. */ + line_coding -> ux_host_class_gser_line_coding_parity = + (ULONG) *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_PARITY); + + /* Finally the data bits. */ + line_coding -> ux_host_class_gser_line_coding_data_bits = + (ULONG) *(data_buffer + UX_HOST_CLASS_GSER_LINE_CODING_DATA_BIT); + } + + /* We free the resources allocated no matter what. */ + _ux_utility_memory_free(data_buffer); + } + break; + + case UX_HOST_CLASS_GSER_IOCTL_SET_LINE_STATE: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_SET_LINE_STATE, gser, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Cast the calling parameter. */ + line_state = (UX_HOST_CLASS_GSER_LINE_STATE *) parameter; + + /* Build the value field. */ + value = (line_state -> ux_host_class_gser_line_state_dtr | + (line_state -> ux_host_class_gser_line_state_rts << 1)); + + /* Send the command to the device. */ + status = _ux_host_class_gser_command(gser, interface_index, UX_HOST_CLASS_GSER_REQ_SET_LINE_STATE, + value, UX_NULL,0); + break; + + case UX_HOST_CLASS_GSER_IOCTL_SEND_BREAK : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_SEND_BREAK, gser, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Build the value field. */ + value = *((ULONG *) parameter); + + /* Send the command to the device. */ + status = _ux_host_class_gser_command(gser, interface_index, UX_HOST_CLASS_GSER_REQ_SEND_BREAK, + value, UX_NULL,0); + break; + + case UX_HOST_CLASS_GSER_IOCTL_ABORT_IN_PIPE : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_ABORT_IN_PIPE, gser, gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_in_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_in_endpoint); + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_GSER_IOCTL_ABORT_OUT_PIPE : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_ABORT_OUT_PIPE, gser, gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_out_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to abort transactions on the bulk Out pipe. */ + _ux_host_stack_endpoint_transfer_abort(gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_out_endpoint); + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_GSER_IOCTL_NOTIFICATION_CALLBACK : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_NOTIFICATION_CALLBACK, gser, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Register a callback when the line state has changed. */ + callback_function = ((VOID (*) (struct UX_HOST_CLASS_GSER_STRUCT *, ULONG, ULONG )) (ALIGN_TYPE)parameter); + gser -> ux_host_class_gser_device_status_change_callback = callback_function; + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_GSER_IOCTL_GET_DEVICE_STATUS : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_IOCTL_GET_DEVICE_STATUS, gser, gser -> ux_host_class_gser_device_state, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Return the device status. */ + * ((ULONG *) parameter) = gser -> ux_host_class_gser_device_state; + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + default: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Function not supported. Return an error. */ + status = UX_FUNCTION_NOT_SUPPORTED; + } + + /* Return status to caller. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_gser_read.c b/common/usbx_host_classes/src/ux_host_class_gser_read.c new file mode 100644 index 0000000..933d046 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_read.c @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the gser interface. The call is */ +/* blocking and only returns when there is either an error or when */ +/* the transfer is complete. */ +/* */ +/* INPUT */ +/* */ +/* gser Pointer to gser class */ +/* data_pointer Pointer to buffer */ +/* requested_length Requested data read */ +/* actual_length Actual data read */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_gser_read(UX_HOST_CLASS_GSER *gser, + ULONG interface_index, + UCHAR *data_pointer, + ULONG requested_length, + ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_READ, gser, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (gser -> ux_host_class_gser_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, gser, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* Start by resetting the actual length of the transfer to zero. */ + *actual_length = 0; + + /* Get the pointer to the bulk in endpoint in the transfer_request. */ + transfer_request = &gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Save the interface number in the Transfer Request. */ + transfer_request -> ux_transfer_request_user_specific = (VOID *)(ALIGN_TYPE)interface_index; + + /* Perform a transfer on the bulk in endpoint until either the transfer is + completed or until there is an error. */ + while (requested_length) + { + + /* Program the maximum authorized length for this transfer request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer_request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_GSER_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer request in case some data was actually received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + + /* There was a non transfer error, no partial transfer to be checked. */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually received and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + + /* Return success to caller. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to receive. */ + requested_length -= transfer_request_length; + } + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_gser_reception_callback.c b/common/usbx_host_classes/src/ux_host_class_gser_reception_callback.c new file mode 100644 index 0000000..098aca0 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_reception_callback.c @@ -0,0 +1,147 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_reception_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the callback from the USBX transfer functions, */ +/* it is called when a full or partial transfer has been done for a */ +/* bulk in transfer. It calls back the application. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_gser_reception_callback (UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_GSER *gser; +UX_HOST_CLASS_GSER_RECEPTION *gser_reception; +ULONG interface_index; + + /* Get the class instance for this transfer request. */ + gser = (UX_HOST_CLASS_GSER *) transfer_request -> ux_transfer_request_class_instance; + + /* The interface index was stored into the user specific field. */ + interface_index = (ULONG) (ALIGN_TYPE) transfer_request -> ux_transfer_request_user_specific; + + /* Get the pointer to the acm reception structure. */ + gser_reception = gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_reception; + + /* Check the state of the transfer. If there is an error, we do not proceed with this report. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* The reception is stopped. */ + gser_reception -> ux_host_class_gser_reception_state = UX_HOST_CLASS_GSER_RECEPTION_STATE_STOPPED; + + /* We do not proceed. */ + return; + + } + + /* And move to the next reception buffer. Check if we are at the end of the application buffer. */ + if (gser_reception -> ux_host_class_gser_reception_data_head + gser_reception -> ux_host_class_gser_reception_block_size >= + gser_reception -> ux_host_class_gser_reception_data_buffer + gser_reception -> ux_host_class_gser_reception_data_buffer_size) + { + + /* We are at the end of the buffer. Move back to the beginning if we have space available. */ + if (gser_reception -> ux_host_class_gser_reception_data_tail == gser_reception -> ux_host_class_gser_reception_data_buffer) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_BUFFER_OVERFLOW, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We have an overflow. We cannot continue. Report to the application. */ + gser_reception -> ux_host_class_gser_reception_callback(gser, UX_BUFFER_OVERFLOW, UX_NULL, 0); + + /* And stop the transfer in progress flag. */ + gser_reception -> ux_host_class_gser_reception_state = UX_HOST_CLASS_GSER_RECEPTION_STATE_STOPPED; + + return; + } + else + + /* Program the head to be at the beginning of the application buffer. */ + gser_reception -> ux_host_class_gser_reception_data_head = gser_reception -> ux_host_class_gser_reception_data_buffer; + + } + else + + /* Program the head to be after the current buffer. */ + gser_reception -> ux_host_class_gser_reception_data_head += gser_reception -> ux_host_class_gser_reception_block_size; + + + /* We need to report this transfer to the application. */ + gser_reception -> ux_host_class_gser_reception_callback(gser, + transfer_request -> ux_transfer_request_completion_code, + transfer_request -> ux_transfer_request_data_pointer, + transfer_request -> ux_transfer_request_actual_length); + + /* Arm another transfer. */ + _ux_host_stack_transfer_request(transfer_request); + + /* There is no status to be reported back to the stack. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_gser_reception_start.c b/common/usbx_host_classes/src/ux_host_class_gser_reception_start.c new file mode 100644 index 0000000..551bd0e --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_reception_start.c @@ -0,0 +1,135 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_reception_start PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a reception with the generic serial class. This*/ +/* allows for non blocking calls based on a packet orientated round */ +/* robbin buffer. When a packet is fully or partially received, an */ +/* application callback function is invoked and a new transfer request */ +/* is rescheduled. */ +/* */ +/* INPUT */ +/* */ +/* gser Pointer to gser class */ +/* gser_reception Pointer to reception struct */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_gser_reception_start (UX_HOST_CLASS_GSER *gser, + UX_HOST_CLASS_GSER_RECEPTION *gser_reception) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG interface_index; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_RECEPTION_START, gser, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (gser -> ux_host_class_gser_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, gser, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Get the interface index. */ + interface_index = gser_reception -> ux_host_class_gser_reception_interface_index; + + /* Start by aligning the head and tail of buffers to the same address supplied by the application. */ + gser_reception -> ux_host_class_gser_reception_data_head = gser_reception -> ux_host_class_gser_reception_data_buffer; + gser_reception -> ux_host_class_gser_reception_data_tail = gser_reception -> ux_host_class_gser_reception_data_buffer; + + /* Get the pointer to the bulk in endpoint in the transfer_request. */ + transfer_request = &gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Save the interface number in the Transfer Request. */ + transfer_request -> ux_transfer_request_user_specific = (VOID *) (ALIGN_TYPE) interface_index; + + /* Initialize the transfer request. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) gser; + transfer_request -> ux_transfer_request_data_pointer = gser_reception -> ux_host_class_gser_reception_data_head; + transfer_request -> ux_transfer_request_requested_length = gser_reception -> ux_host_class_gser_reception_block_size; + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_gser_reception_callback; + + /* Save the acm reception structure in the acm structure. */ + gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_reception = gser_reception; + + /* And declare we have a transfer in progress. */ + gser_reception -> ux_host_class_gser_reception_state = UX_HOST_CLASS_GSER_RECEPTION_STATE_STARTED; + + /* Arm a first transfer on the bulk in endpoint. There is a callback to this function so we return to the caller + right away. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* We do not know if the first transfer was successful yet. If the status is not OK, we need to stop the transfer + in progress flag. */ + if (status != UX_SUCCESS) + gser_reception -> ux_host_class_gser_reception_state = UX_HOST_CLASS_GSER_RECEPTION_STATE_STOPPED; + + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_gser_reception_stop.c b/common/usbx_host_classes/src/ux_host_class_gser_reception_stop.c new file mode 100644 index 0000000..7f9b4d4 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_reception_stop.c @@ -0,0 +1,111 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_reception_stop PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a reception with the generic modem. This way */ +/* allows for non blocking calls based on a packet orientated round */ +/* robbin buffer. When a packet is fully or partially received, an */ +/* application callback function is invoked and a new transfer request */ +/* is rescheduled. */ +/* */ +/* INPUT */ +/* */ +/* gser Pointer to gser class */ +/* gser_reception Pointer to reception struct */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_gser_reception_stop (UX_HOST_CLASS_GSER *gser, + UX_HOST_CLASS_GSER_RECEPTION *gser_reception) +{ + +ULONG interface_index; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_RECEPTION_STOP, gser, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (gser -> ux_host_class_gser_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, gser, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Check if we do have transfers for this application. If none, nothing to do. */ + if (gser_reception -> ux_host_class_gser_reception_state == UX_HOST_CLASS_GSER_RECEPTION_STATE_STOPPED) + return(UX_SUCCESS); + + /* Get the interface index. */ + interface_index = gser_reception -> ux_host_class_gser_reception_interface_index; + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_in_endpoint); + + /* Declare the reception stopped. */ + gser_reception -> ux_host_class_gser_reception_state = UX_HOST_CLASS_GSER_RECEPTION_STATE_STOPPED; + + /* This function never really fails. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_gser_write.c b/common/usbx_host_classes/src/ux_host_class_gser_write.c new file mode 100644 index 0000000..9fbb1cc --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_gser_write.c @@ -0,0 +1,204 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Generic Serial Host module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_gser.h" +#include "ux_host_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_gser_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the gser interface. The call is blocking */ +/* and only returns when there is either an error or when the transfer */ +/* is complete. */ +/* */ +/* INPUT */ +/* */ +/* gser Pointer to gser class */ +/* data_pointer Pointer to data to write */ +/* requested_length Length of data to write */ +/* actual_length Actual length of data written */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_gser_write(UX_HOST_CLASS_GSER *gser, + ULONG interface_index, + UCHAR * data_pointer, + ULONG requested_length, + ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_GSER_WRITE, gser, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (gser -> ux_host_class_gser_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, gser, 0, 0, UX_TRACE_ERRORS, 0, 0) + + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* Start by resetting the actual length of the transfer. */ + *actual_length = 0; + + /* Get the pointer to the bulk out endpoint transfer request. */ + transfer_request = &gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Save the interface number in the Transfer Request. */ + transfer_request -> ux_transfer_request_user_specific = (VOID *) (ALIGN_TYPE) interface_index; + + /* Perform a transfer on the bulk out endpoint until either the transfer is + completed or when there is an error. */ + do + { + + /* Program the maximum authorized length for this transfer_request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_GSER_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer_request in case some data actually went out. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be sent. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually sent and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + + /* Return success. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to send out. */ + requested_length -= transfer_request_length; + + } while (requested_length != 0); + + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&gser -> ux_host_class_gser_interface_array[interface_index].ux_host_class_gser_semaphore); + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_activate.c b/common/usbx_host_classes/src/ux_host_class_hid_activate.c new file mode 100644 index 0000000..723e8a3 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_activate.c @@ -0,0 +1,190 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs the enumeration of the HID class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_client_search HID client search */ +/* _ux_host_class_hid_configure Configure HID */ +/* _ux_host_class_hid_descriptor_parse Parse descriptor */ +/* _ux_host_class_hid_interrupt_endpoint_search Search endpoint */ +/* _ux_host_class_hid_instance_clean Clean up instance resources */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy class instance */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_semaphore_create Create semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_INTERFACE *interface; +UX_HOST_CLASS_HID *hid; +UINT status; + + + /* The HID is always activated by the interface descriptor and not the + device descriptor. */ + interface = (UX_INTERFACE *) command -> ux_host_class_command_container; + + /* Instantiate this HID class */ + hid = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY,sizeof(UX_HOST_CLASS_HID)); + if (hid == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance. */ + hid -> ux_host_class_hid_class = command -> ux_host_class_command_class_ptr; + + /* Store the interface container into the HID class instance. */ + hid -> ux_host_class_hid_interface = interface; + + /* Store the device container into the HID class instance. */ + hid -> ux_host_class_hid_device = interface -> ux_interface_configuration -> ux_configuration_device; + + /* This instance of the device must also be stored in the interface container. */ + interface -> ux_interface_class_instance = (VOID *) hid; + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(command -> ux_host_class_command_class_ptr, (VOID *) hid); + + /* Configure the HID. */ + status = _ux_host_class_hid_configure(hid); + + /* If configure is done success, goes on. */ + if (status == UX_SUCCESS) + { + + /* Get the HID descriptor and parse it. */ + status = _ux_host_class_hid_descriptor_parse(hid); + } + + /* If HID descriptor parse is done success, goes on. */ + if (status == UX_SUCCESS) + { + + /* Search the HID interrupt endpoint but do not start it. */ + status = _ux_host_class_hid_interrupt_endpoint_search(hid); + } + + /* If HID interrupt endpoint is found, goes on. */ + if (status == UX_SUCCESS) + { + + /* Create the semaphore to protect multiple threads from accessing the same + storage instance. */ + status = _ux_utility_semaphore_create(&hid -> ux_host_class_hid_semaphore, "ux_host_class_hid_semaphore", 1); + + if (status == UX_SUCCESS) + { + + /* If all is fine, try to locate the HID client for this HID device. */ + _ux_host_class_hid_client_search(hid); + + /* Mark the HID class as live now. */ + hid -> ux_host_class_hid_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* We may need to inform the application if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_ACTIVATE, hid, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, hid, 0, 0, 0) + + /* Return completion code. */ + return(status); + } + else + { + status = UX_SEMAPHORE_ERROR; + } + } + + /* Clean interrupt endpoint. */ + if (hid -> ux_host_class_hid_interrupt_endpoint && + hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer) + _ux_utility_memory_free(hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer); + + /* Clean instance. */ + _ux_host_class_hid_instance_clean(hid); + + /* Error, destroy the class instance and return error code. */ + _ux_host_stack_class_instance_destroy(hid -> ux_host_class_hid_class, (VOID *) hid); + + /* Unmount instance. */ + interface -> ux_interface_class_instance = UX_NULL; + + /* Free instance. */ + _ux_utility_memory_free(hid); + + /* Return error code. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_client_register.c b/common/usbx_host_classes/src/ux_host_class_hid_client_register.c new file mode 100644 index 0000000..945ef98 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_client_register.c @@ -0,0 +1,183 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + +UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(UX_HOST_CLASS_HID_MAX_CLIENTS, sizeof(UX_HOST_CLASS_HID_CLIENT)), UX_HOST_CLASS_HID_MAX_CLIENTS_mem_alloc_ovf) + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_client_register PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers a USB HID client to the HID class. The */ +/* mechanism is similar to the USB stack class registration. The Class */ +/* must specify an entry point for the USB stack to send commands */ +/* such as: */ +/* */ +/* UX_HOST_CLASS_COMMAND_QUERY */ +/* UX_HOST_CLASS_COMMAND_ACTIVATE */ +/* UX_HOST_CLASS_COMMAND_DESTROY */ +/* */ +/* Note: The C string of hid_client_name must be NULL-terminated and */ +/* the length of it (without the NULL-terminator itself) must be no */ +/* larger than UX_HOST_CLASS_HID_MAX_CLIENT_NAME_LENGTH. */ +/* */ +/* INPUT */ +/* */ +/* hid_client_name Name of HID client */ +/* hid_client_handler Handler for HID client */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_get Get class */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_copy Copy memory block */ +/* _ux_utility_string_length_check Check C string and return */ +/* length if null-terminated */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_client_register(UCHAR *hid_client_name, + UINT (*hid_client_handler)(struct UX_HOST_CLASS_HID_CLIENT_COMMAND_STRUCT *)) +{ + +UX_HOST_CLASS *class; +ULONG hid_client_index; +UINT status; +UX_HOST_CLASS_HID_CLIENT *hid_client; +UINT client_name_length = 0; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_CLIENT_REGISTER, hid_client_name, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Get the length of the client name (exclude null-terminator). */ + status = _ux_utility_string_length_check(hid_client_name, &client_name_length, UX_HOST_CLASS_HID_MAX_CLIENT_NAME_LENGTH); + if (status) + return(status); + + /* We need to locate our class container. */ + status = _ux_host_stack_class_get(_ux_system_host_class_hid_name, &class); + + /* If we cannot get the class container, it means the HID class was not registered. */ + if (status != UX_SUCCESS) + return(status); + + /* From the class container, we get the client pointer which has the list of + HID clients. If the pointer is NULL, the client list was not assigned. */ + if (class -> ux_host_class_client == UX_NULL) + { + + /* Allocate memory for the class client. + * Allocate size overflow static checked outside the function. + */ + class -> ux_host_class_client = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, + sizeof(UX_HOST_CLASS_HID_CLIENT)*UX_HOST_CLASS_HID_MAX_CLIENTS); + + /* Check for successful allocation. */ + if (class -> ux_host_class_client == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + } + + /* De-reference the client pointer into a HID client array pointer. */ + hid_client = (UX_HOST_CLASS_HID_CLIENT *) class -> ux_host_class_client; + + /* We need to parse the HID client handler table to find an empty spot. */ + for (hid_client_index = 0; hid_client_index < UX_HOST_CLASS_HID_MAX_CLIENTS; hid_client_index++) + { + + /* Check if this HID client is already used. */ + if (hid_client -> ux_host_class_hid_client_status == UX_UNUSED) + { + + /* We have found a free container for the HID client. Copy the name (with null-terminator). */ + _ux_utility_memory_copy(hid_client -> ux_host_class_hid_client_name, hid_client_name, client_name_length + 1); + + /* Memorize the handler address of this client. */ + hid_client -> ux_host_class_hid_client_handler = hid_client_handler; + + /* Mark it as being in use. */ + hid_client -> ux_host_class_hid_client_status = UX_USED; + + /* Return successful completion. */ + return(UX_SUCCESS); + } + else + { + + /* Do a sanity check to make sure the handler is not already installed by + mistake. To verify this, we simple check for the handler entry point. */ + if (hid_client -> ux_host_class_hid_client_handler == hid_client_handler) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_ALREADY_INSTALLED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_ALREADY_INSTALLED, hid_client_name, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_ALREADY_INSTALLED); + } + } + + /* Try the next class. */ + hid_client++; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_ARRAY_FULL); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_ARRAY_FULL, hid_client_name, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* No more entries in the class table. */ + return(UX_MEMORY_ARRAY_FULL); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_client_search.c b/common/usbx_host_classes/src/ux_host_class_hid_client_search.c new file mode 100644 index 0000000..1d96ce9 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_client_search.c @@ -0,0 +1,149 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_client_search PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function searches for a HID client that wants to own this HID */ +/* device. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_hid_client_handler) HID client handler */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_client_search(UX_HOST_CLASS_HID *hid) +{ + +UX_HOST_CLASS_HID_CLIENT *hid_client; +ULONG hid_client_index; +UINT status; +UX_HOST_CLASS_HID_CLIENT_COMMAND hid_client_command; + + + /* In order to search a HID client, we need both the main page and the main usage. */ + hid_client_command.ux_host_class_hid_client_command_page = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_main_page; + hid_client_command.ux_host_class_hid_client_command_usage = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_main_usage & 0xffff; + hid_client_command.ux_host_class_hid_client_command_instance = hid; + hid_client_command.ux_host_class_hid_client_command_container = (VOID *) hid -> ux_host_class_hid_class; + hid_client_command.ux_host_class_hid_client_command_request = UX_HOST_CLASS_COMMAND_QUERY; + + /* Dereference the client pointer into a HID client pointer. */ + hid_client = (UX_HOST_CLASS_HID_CLIENT *) hid -> ux_host_class_hid_class -> ux_host_class_client; + + /* If the hid_client pointer is NULL, the array of clients was not initialized. */ + if (hid_client == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_UNKNOWN); + } + + /* We need to parse the hid client driver table to find a registered client. */ + for (hid_client_index = 0; hid_client_index < UX_HOST_CLASS_HID_MAX_CLIENTS; hid_client_index++) + { + + /* Check if this HID client is registered. */ + if (hid_client -> ux_host_class_hid_client_status == UX_USED) + { + + /* Call the HID client with a query command. */ + status = hid_client -> ux_host_class_hid_client_handler(&hid_client_command); + + /* Have we found a HID client? */ + if (status == UX_SUCCESS) + { + + /* Update the command to activate the client. */ + hid_client_command.ux_host_class_hid_client_command_request = UX_HOST_CLASS_COMMAND_ACTIVATE; + + /* Memorize the client for this HID device. */ + hid -> ux_host_class_hid_client = hid_client; + + /* Call the HID client with an activate command. */ + status = hid_client -> ux_host_class_hid_client_handler(&hid_client_command); + + /* Unmount the client if activation fail. */ + if (status != UX_SUCCESS) + hid -> ux_host_class_hid_client = UX_NULL; + + /* Return completion status. */ + return(status); + } + } + + /* Try the next HID client. */ + hid_client++; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_HOST_CLASS_HID_UNKNOWN); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_configure.c b/common/usbx_host_classes/src/ux_host_class_hid_configure.c new file mode 100644 index 0000000..71641a2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_configure.c @@ -0,0 +1,139 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to the */ +/* HID. Once the HID is configured, its interface will be activated */ +/* and all the endpoints enumerated (1 interrupt endpoint in the case */ +/* of the HID). */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get Get interface */ +/* _ux_host_stack_device_configuration_get Get configuration */ +/* _ux_host_stack_device_configuration_select Select configuration */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_configure(UX_HOST_CLASS_HID *hid) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_DEVICE *device; +UX_DEVICE *parent_device; + + + /* If the device has been configured already, we don't need to do it again. */ + if (hid -> ux_host_class_hid_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* A HID normally has one configuration. So retrieve the 1st configuration only. */ + status = _ux_host_stack_device_configuration_get(hid -> ux_host_class_hid_device, 0, &configuration); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, hid -> ux_host_class_hid_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Get the device container for this configuration. */ + device = configuration -> ux_configuration_device; + + /* Get the parent container for this device. */ + parent_device = device -> ux_device_parent; + + /* Check the HID power source and check the parent power source for + incompatible connections. */ + if (hid -> ux_host_class_hid_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* If the device is NULL, the parent is the root hid and we don't have to worry. + If the parent is not the root HID, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration. */ + status = _ux_host_stack_device_configuration_select(configuration); + + /* If the operation went well, the hid default alternate setting for the HID interface is active + and the interrupt endpoint is now enabled. We have to memorize the first interface since the + interrupt endpoint is hooked to it. */ + status = _ux_host_stack_configuration_interface_get(configuration, 0, 0, &hid -> ux_host_class_hid_interface); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_deactivate.c b/common/usbx_host_classes/src/ux_host_class_hid_deactivate.c new file mode 100644 index 0000000..7b8574a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_deactivate.c @@ -0,0 +1,155 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the HID has been */ +/* removed from the bus either directly or indirectly. The interrupt */ +/* pipe will be destroyed and the instanced removed. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_hid_client_handler) HID client handler */ +/* _ux_host_class_hid_instance_clean HID instance clean */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort transfer */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_thread_schedule_other Schedule other threads */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT_COMMAND hid_client_command; +UX_TRANSFER *transfer_request; +UINT status; + + + /* Get the instance for this class. */ + hid = (UX_HOST_CLASS_HID *) command -> ux_host_class_command_instance; + + /* The HID is being shut down. */ + hid -> ux_host_class_hid_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* We need to abort transactions on the interrupt pipe. */ + _ux_host_stack_endpoint_transfer_abort(hid -> ux_host_class_hid_interrupt_endpoint); + + /* We need to inform the HID client, if any, of the deactivation. */ + hid_client_command.ux_host_class_hid_client_command_instance = (VOID *) hid; + hid_client_command.ux_host_class_hid_client_command_container = (VOID *) hid -> ux_host_class_hid_class; + hid_client_command.ux_host_class_hid_client_command_request = UX_HOST_CLASS_COMMAND_DEACTIVATE; + + /* Call the HID client with a deactivate command if there was a client registered. */ + if (hid -> ux_host_class_hid_client != UX_NULL) + hid -> ux_host_class_hid_client -> ux_host_class_hid_client_handler(&hid_client_command); + + /* Clean all the HID memory fields. */ + _ux_host_class_hid_instance_clean(hid); + + /* If the Hid class instance has a interrupt pipe with a data payload associated with it + it must be freed. */ + transfer_request = &hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request; + + /* Then de allocate the memory. */ + _ux_utility_memory_free(transfer_request -> ux_transfer_request_data_pointer); + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(hid -> ux_host_class_hid_class, (VOID *) hid); + + /* Destroy the semaphore. */ + _ux_utility_semaphore_delete(&hid -> ux_host_class_hid_semaphore); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, hid -> ux_host_class_hid_class, (VOID *) hid); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_DEACTIVATE, hid, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(hid); + + /* The HID is now free again. */ + _ux_utility_memory_free(hid); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_descriptor_parse.c b/common/usbx_host_classes/src/ux_host_class_hid_descriptor_parse.c new file mode 100644 index 0000000..10f0dbb --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_descriptor_parse.c @@ -0,0 +1,254 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_descriptor_parse PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the HID descriptor and parses it. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_report_descriptor_get */ +/* Get HID report descriptor */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_descriptor_parse(UX_HOST_CLASS_HID *hid) +{ + +UCHAR *descriptor; +UCHAR *start_descriptor; +UX_CONFIGURATION_DESCRIPTOR configuration_descriptor; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UX_HID_DESCRIPTOR hid_descriptor; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UINT status; +ULONG total_configuration_length; +UINT descriptor_length; +UINT descriptor_type; +ULONG current_interface; + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the descriptor. Since we do not know the size of the + descriptor, we first read the first bytes. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_CONFIGURATION_DESCRIPTOR_LENGTH); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Memorize the descriptor start address. */ + start_descriptor = descriptor; + + /* Reset the current interface to keep compiler warnings happy. */ + current_interface = 0; + + /* Create a transfer request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = UX_CONFIGURATION_DESCRIPTOR_LENGTH; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_CONFIGURATION_DESCRIPTOR_ITEM << 8; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == UX_CONFIGURATION_DESCRIPTOR_LENGTH)) + { + + /* Parse the descriptor so that we can read the total length. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, (UCHAR *) &configuration_descriptor); + + /* We don't need this descriptor now. */ + _ux_utility_memory_free(descriptor); + + /* Reallocate the memory necessary for the reading the entire descriptor. */ + total_configuration_length = configuration_descriptor.wTotalLength; + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, total_configuration_length); + if(descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Save this descriptor address. */ + start_descriptor = descriptor; + + /* Read the descriptor again with the correct length this time. */ + transfer_request -> ux_transfer_request_requested_length = total_configuration_length; + + /* Since the address of the descriptor may have changed, reprogram it. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == configuration_descriptor.wTotalLength)) + { + + /* The HID descriptor is embedded within the configuration descriptor. We parse the + entire descriptor to locate the HID portion. */ + while (total_configuration_length) + { + + /* Gather the length and type of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Error, release the memory and return an error. */ + _ux_utility_memory_free(start_descriptor); + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Check the type for an interface descriptor. */ + if (descriptor_type == UX_INTERFACE_DESCRIPTOR_ITEM) + { + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, + _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, + (UCHAR *) &interface_descriptor); + + /* Memorize the interface we are scanning. */ + current_interface = interface_descriptor.bInterfaceNumber; + + } + + /* Check the type for an interface descriptor. */ + /* Check if the descriptor belongs to interface attached to this instance. */ + if (descriptor_type == UX_HOST_CLASS_HID_DESCRIPTOR) + { + + /* Ensure this interface is the one we need to scan. */ + if (current_interface == hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber) + { + + /* Obtain the length of the HID descriptor. We need to make machine + independent first. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_hid_descriptor_structure, + UX_HID_DESCRIPTOR_ENTRIES, (UCHAR *) &hid_descriptor); + + /* We have found the hid descriptor. Now we should get the HID report descriptor. */ + status = _ux_host_class_hid_report_descriptor_get(hid, hid_descriptor.wItemLength); + + /* Release the memory. */ + _ux_utility_memory_free(start_descriptor); + + /* Return completion status. */ + return(status); + } + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_configuration_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Release the memory. */ + _ux_utility_memory_free(start_descriptor); + + /* Return an error. */ + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_configuration_length -= descriptor_length; + } + } + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Free all used resources. */ + _ux_utility_memory_free(start_descriptor); + + /* Return an error. */ + return(UX_DESCRIPTOR_CORRUPTED); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_entry.c b/common/usbx_host_classes/src/ux_host_class_hid_entry.c new file mode 100644 index 0000000..c90d204 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_entry.c @@ -0,0 +1,125 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the HID class. It will be */ +/* called by the USB stack enumeration module when there is a new */ +/* device on the bus or when there is a device extraction. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_activate Activate HID class */ +/* _ux_host_class_hid_deactivate Deactivate HID class */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if ((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) && + (command -> ux_host_class_command_class == UX_HOST_CLASS_HID_CLASS)) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + + status = _ux_host_class_hid_activate(command); + + return(status); + + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_hid_deactivate(command); + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error status. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_field_decompress.c b/common/usbx_host_classes/src/ux_host_class_hid_field_decompress.c new file mode 100644 index 0000000..9653466 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_field_decompress.c @@ -0,0 +1,158 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_field_decompress PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will decompress a field and return the usage/value. */ +/* */ +/* INPUT */ +/* */ +/* hid_field Pointer to HID field */ +/* report_buffer Pointer to report buffer */ +/* client_report Pointer to client report */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_field_decompress(UX_HOST_CLASS_HID_FIELD *hid_field, UCHAR *report_buffer, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report) +{ + +ULONG field_report_count; +ULONG field_report_size; +ULONG data_offset_byte; +ULONG data_offset_bit; +ULONG data_offset_bit_in_report; +ULONG field_value; +ULONG field_value_bit_shifting; +ULONG field_usage; +ULONG report_content; + + + /* Calculate the address of the beginning of the field in the report. */ + data_offset_byte = (hid_field -> ux_host_class_hid_field_report_offset >> 3); + + /* Calculate the bit start address. Hopefully things will be on a boundary but not necessary. */ + data_offset_bit = hid_field -> ux_host_class_hid_field_report_offset & 7; + + /* Each report field has a report_count value. This count is used to extract values from the + incoming report and build each usage/value instance. */ + for (field_report_count = 0; field_report_count < hid_field -> ux_host_class_hid_field_report_count; field_report_count++) + { + + /* Get the report size in bits. */ + field_report_size = hid_field -> ux_host_class_hid_field_report_size; + + /* We use the bit offset for this report and not the generic field bit offset. */ + data_offset_bit_in_report = data_offset_bit; + + /* Reset the local value. */ + field_value = 0; + + /* And start with bit 0 in the target value. */ + field_value_bit_shifting = 0; + + /* Build the value field bit by bit. */ + while (field_report_size-- != 0) + { + + /* Read the content. This method is redundant if we are not changing byte but it + makes the algorithm much easier. */ + report_content = (ULONG) *(report_buffer + data_offset_byte + (data_offset_bit_in_report >> 3)); + + /* Shift the current value content to allow space to store the new bit. */ + field_value |= ((report_content >> (data_offset_bit_in_report & 7)) & 1) << field_value_bit_shifting; + + /* Move to next bit in the report. */ + data_offset_bit_in_report++; + + /* And the next bit in the value. */ + field_value_bit_shifting++; + } + + /* The Usage value will depend if the data is defined as a variable or an array in the HID report. */ + if (hid_field -> ux_host_class_hid_field_value & UX_HOST_CLASS_HID_ITEM_VARIABLE) + { + + /* Take the usage directly from the usage array. */ + field_usage = *(hid_field -> ux_host_class_hid_field_usages + field_report_count); + } + else + { + + /* This is an array, so compute the usage from the min value, the report count and the + computed report value. */ + field_usage = hid_field -> ux_host_class_hid_field_usage_min + (ULONG)((SLONG)field_value - hid_field -> ux_host_class_hid_field_logical_min); + + /* Also add the usage page. */ + field_usage |= (hid_field -> ux_host_class_hid_field_usage_page << 16); + } + + /* Put the value and the usage into the caller's buffer. */ + *(client_report -> ux_host_class_hid_client_report_buffer + client_report -> ux_host_class_hid_client_report_actual_length) = field_usage; + client_report -> ux_host_class_hid_client_report_actual_length++; + *(client_report -> ux_host_class_hid_client_report_buffer + client_report -> ux_host_class_hid_client_report_actual_length) = field_value; + client_report -> ux_host_class_hid_client_report_actual_length++; + + /* Calculate the next address for this field. */ + data_offset_bit += hid_field -> ux_host_class_hid_field_report_size; + } + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_global_item_parse.c b/common/usbx_host_classes/src/ux_host_class_hid_global_item_parse.c new file mode 100644 index 0000000..58b176f --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_global_item_parse.c @@ -0,0 +1,249 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_global_item_parse PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses a global item from the report descriptor. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* item Pointer to item */ +/* descriptor Pointer to descriptor */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_item_data_get Get data item */ +/* _ux_utility_memory_copy Copy memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_global_item_parse(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_ITEM *item, UCHAR *descriptor) +{ + +UX_HOST_CLASS_HID_PARSER *hid_parser; + + + /* Get the temporary parser structure pointer. */ + hid_parser = &hid -> ux_host_class_hid_parser; + + /* Get the tag of the item structure and process it. */ + switch(item -> ux_host_class_hid_item_report_tag) + { + + case UX_HOST_CLASS_HID_GLOBAL_TAG_USAGE_PAGE: + + /* Usage Page Tag. */ + hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_usage_page = + _ux_host_class_hid_item_data_get(descriptor, item); + break; + + + case UX_HOST_CLASS_HID_GLOBAL_TAG_LOGICAL_MINIMUM: + + /* Logical Minimum Tag. */ + hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_logical_min = + (SLONG) _ux_host_class_hid_item_data_get(descriptor, item); + break; + + + case UX_HOST_CLASS_HID_GLOBAL_TAG_LOGICAL_MAXIMUM: + + /* Logical Maximum Tag. */ + hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_logical_max = + (SLONG) _ux_host_class_hid_item_data_get(descriptor, item); + break; + + + case UX_HOST_CLASS_HID_GLOBAL_TAG_PHYSICAL_MINIMUM: + + /* Physical Minimum Tag. */ + hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_physical_min = + (SLONG) _ux_host_class_hid_item_data_get(descriptor, item); + break; + + + case UX_HOST_CLASS_HID_GLOBAL_TAG_PHYSICAL_MAXIMUM: + + /* Physical Maximum Tag. */ + hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_physical_max = + (SLONG) _ux_host_class_hid_item_data_get(descriptor, item); + break; + + + case UX_HOST_CLASS_HID_GLOBAL_TAG_UNIT_EXPONENT: + + /* Unit Exponent Tag. */ + hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_unit_expo = + _ux_host_class_hid_item_data_get(descriptor, item); + break; + + + case UX_HOST_CLASS_HID_GLOBAL_TAG_UNIT: + + /* Unit tag. */ + hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_unit = + _ux_host_class_hid_item_data_get(descriptor, item); + break; + + + case UX_HOST_CLASS_HID_GLOBAL_TAG_REPORT_SIZE: + + /* Report Size tag. */ + hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_size = + _ux_host_class_hid_item_data_get(descriptor, item); + + if (hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_size > UX_HOST_CLASS_HID_REPORT_SIZE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_OVERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_REPORT_OVERFLOW); + } + + break; + + + case UX_HOST_CLASS_HID_GLOBAL_TAG_REPORT_ID: + + /* Report ID tag. */ + hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_id = + _ux_host_class_hid_item_data_get(descriptor, item); + break; + + + case UX_HOST_CLASS_HID_GLOBAL_TAG_REPORT_COUNT: + + /* Report Count tag. */ + hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_count = + _ux_host_class_hid_item_data_get(descriptor, item); + + if (hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_count > UX_HOST_CLASS_HID_USAGES) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_USAGE_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_USAGE_OVERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_USAGE_OVERFLOW); + } + + break; + + case UX_HOST_CLASS_HID_GLOBAL_TAG_PUSH: + + /* Push tag. */ + if (hid_parser -> ux_host_class_hid_parser_number_global >= UX_HOST_CLASS_HID_MAX_GLOBAL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_PUSH_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_PUSH_OVERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_PUSH_OVERFLOW); + } + + else + _ux_utility_memory_copy(&hid_parser -> ux_host_class_hid_parser_global_pool[hid_parser -> ux_host_class_hid_parser_number_global++], + &hid_parser -> ux_host_class_hid_parser_global, sizeof(UX_HOST_CLASS_HID_GLOBAL_ITEM)); + break; + + + case UX_HOST_CLASS_HID_GLOBAL_TAG_POP: + + /* Pop tag. */ + if(hid_parser -> ux_host_class_hid_parser_number_global == 0) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_POP_UNDERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_POP_UNDERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_POP_UNDERFLOW); + } + else + _ux_utility_memory_copy(&hid_parser -> ux_host_class_hid_parser_global, + &hid_parser -> ux_host_class_hid_parser_global_pool[--hid_parser -> ux_host_class_hid_parser_number_global], + sizeof(UX_HOST_CLASS_HID_GLOBAL_ITEM)); + + break; + + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_TAG_UNSUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_TAG_UNSUPPORTED, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* This tag was not recognized or is not supported. */ + return(UX_HOST_CLASS_HID_TAG_UNSUPPORTED); + } + + /* We get here when the tag has been processed successfully. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_idle_get.c b/common/usbx_host_classes/src/ux_host_class_hid_idle_get.c new file mode 100644 index 0000000..acf0f01 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_idle_get.c @@ -0,0 +1,143 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_idle_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a GET_IDLE to the HID device. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* idle_time Idle time */ +/* report_id Report ID */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_idle_get(UX_HOST_CLASS_HID *hid, USHORT *idle_time, USHORT report_id) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UCHAR *idle_byte; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_IDLE_GET, hid, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the idle byte. */ + idle_byte = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 1); + if (idle_byte == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Return error status. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Create a transfer request for the GET_IDLE request. */ + transfer_request -> ux_transfer_request_data_pointer = idle_byte; + transfer_request -> ux_transfer_request_requested_length = 1; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_GET_IDLE; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = report_id; + transfer_request -> ux_transfer_request_index = hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and for the entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 1)) + *idle_time = (USHORT) *idle_byte; + + /* Free used resources. */ + _ux_utility_memory_free(idle_byte); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Return the completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_idle_set.c b/common/usbx_host_classes/src/ux_host_class_hid_idle_set.c new file mode 100644 index 0000000..a7fd64d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_idle_set.c @@ -0,0 +1,121 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_idle_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a SET_IDLE to the HID device. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* idle_time Idle time */ +/* report_id Report ID */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_idle_set(UX_HOST_CLASS_HID *hid, USHORT idle_time, USHORT report_id) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_IDLE_SET, hid, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Create a transfer request for the SET_IDLE request. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_SET_IDLE; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = (UINT)((idle_time << 8) | report_id); + transfer_request -> ux_transfer_request_index = hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Return the function status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_instance_clean.c b/common/usbx_host_classes/src/ux_host_class_hid_instance_clean.c new file mode 100644 index 0000000..5e9d52c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_instance_clean.c @@ -0,0 +1,206 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_instance_clean PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cleans all the components of a HID instance. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_instance_clean(UX_HOST_CLASS_HID *hid) +{ + +UX_HOST_CLASS_HID_PARSER *hid_parser; +UX_HOST_CLASS_HID_REPORT *hid_report; +UX_HOST_CLASS_HID_REPORT *hid_next_report; +UX_HOST_CLASS_HID_FIELD *hid_field; +UX_HOST_CLASS_HID_FIELD *hid_next_field; + + + /* Get the parser structure pointer. */ + hid_parser = &hid -> ux_host_class_hid_parser; + + /* Each report list of the parser should be cleaned: Input report. */ + hid_report = hid_parser -> ux_host_class_hid_parser_input_report; + while (hid_report != UX_NULL) + { + + /* Get the next report before we clean the current report. */ + hid_next_report = hid_report -> ux_host_class_hid_report_next_report; + + /* Get the first field in the report. */ + hid_field = hid_report -> ux_host_class_hid_report_field; + + /* Clean all the fields attached. */ + while (hid_field != UX_NULL) + { + + /* Get the next field before we clean the current field. */ + hid_next_field = hid_field -> ux_host_class_hid_field_next_field; + + /* Free the usage table. */ + if (hid_field -> ux_host_class_hid_field_usages != UX_NULL) + _ux_utility_memory_free(hid_field -> ux_host_class_hid_field_usages); + + /* Free the value table. */ + if (hid_field -> ux_host_class_hid_field_values != UX_NULL) + _ux_utility_memory_free(hid_field -> ux_host_class_hid_field_values); + + /* Now free the field memory. */ + _ux_utility_memory_free(hid_field); + + /* Next field. */ + hid_field = hid_next_field; + } + + /* Free the report. */ + _ux_utility_memory_free(hid_report); + + /* Next report. */ + hid_report = hid_next_report; + } + + /* Each report list of the parser should be cleaned: Output report. */ + hid_report = hid_parser -> ux_host_class_hid_parser_output_report; + while (hid_report != UX_NULL) + { + + /* Get the next report before we clean the current report. */ + hid_next_report = hid_report -> ux_host_class_hid_report_next_report; + + /* Get the first field in the report. */ + hid_field = hid_report -> ux_host_class_hid_report_field; + + /* Clean all the fields attached. */ + while (hid_field != UX_NULL) + { + + /* Get the next field before we clean the current field. */ + hid_next_field = hid_field -> ux_host_class_hid_field_next_field; + + /* Free the usage table. */ + if (hid_field -> ux_host_class_hid_field_usages != UX_NULL) + _ux_utility_memory_free(hid_field -> ux_host_class_hid_field_usages); + + /* Free the value table. */ + if (hid_field -> ux_host_class_hid_field_values != UX_NULL) + _ux_utility_memory_free(hid_field -> ux_host_class_hid_field_values); + + /* Now free the field memory. */ + _ux_utility_memory_free(hid_field); + + /* Next field. */ + hid_field = hid_next_field; + } + + /* Free the report. */ + _ux_utility_memory_free(hid_report); + + /* Next report. */ + hid_report = hid_next_report; + } + + /* Each report list of the parser should be cleaned: Feature report. */ + hid_report = hid_parser -> ux_host_class_hid_parser_feature_report; + while (hid_report != UX_NULL) + { + + /* Get the next report before we clean the current report. */ + hid_next_report = hid_report -> ux_host_class_hid_report_next_report; + + /* Get the first field in the report. */ + hid_field = hid_report -> ux_host_class_hid_report_field; + + /* Clean all the fields attached. */ + while (hid_field != UX_NULL) + { + + /* Get the next field before we clean the current field. */ + hid_next_field = hid_field -> ux_host_class_hid_field_next_field; + + /* Free the usage table. */ + if (hid_field -> ux_host_class_hid_field_usages != UX_NULL) + _ux_utility_memory_free(hid_field -> ux_host_class_hid_field_usages); + + /* Free the value table. */ + if (hid_field -> ux_host_class_hid_field_values != UX_NULL) + _ux_utility_memory_free(hid_field -> ux_host_class_hid_field_values); + + /* Now free the field memory. */ + _ux_utility_memory_free(hid_field); + + /* Next field. */ + hid_field = hid_next_field; + } + + /* Free the report. */ + _ux_utility_memory_free(hid_report); + + /* Next report. */ + hid_report = hid_next_report; + } + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_interrupt_endpoint_search.c b/common/usbx_host_classes/src/ux_host_class_hid_interrupt_endpoint_search.c new file mode 100644 index 0000000..4e8988d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_interrupt_endpoint_search.c @@ -0,0 +1,135 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_interrupt_endpoint_search PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function searches for the handle of the only interrupt */ +/* endpoint in the default alternate setting of the HID interface. */ +/* The interrupt endpoint should always be there. The actual first */ +/* transfer on the interrupt endpoint does not start until a HID */ +/* client has claimed ownership of the HID device. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_interrupt_endpoint_search(UX_HOST_CLASS_HID *hid) +{ + +UINT status; +UX_INTERFACE *interface; +UX_ENDPOINT *endpoint; +UX_TRANSFER *transfer_request; + + + /* Search the interrupt endpoint. It is attached to the interface container. */ + interface = hid -> ux_host_class_hid_interface; + endpoint = interface -> ux_interface_first_endpoint; + while(endpoint != UX_NULL) + { + + /* Found interrupt IN endpoint. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)) + { + + /* The endpoint is correct, save it. */ + hid -> ux_host_class_hid_interrupt_endpoint = endpoint; + + /* Fill in the transfer request with the length requested for this endpoint. */ + transfer_request = &endpoint -> ux_endpoint_transfer_request; + transfer_request -> ux_transfer_request_requested_length = hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + transfer_request -> ux_transfer_request_actual_length = 0; + + /* The direction is always IN for the HID interrupt endpoint. */ + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN; + + /* There is a callback function associated with the transfer request, so we need the class instance. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) hid; + + /* Interrupt transactions have a completion routine. */ + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_hid_transfer_request_completed; + + /* Obtain a buffer for this transaction. The buffer will always be reused. */ + transfer_request -> ux_transfer_request_data_pointer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + transfer_request -> ux_transfer_request_requested_length); + + /* If the endpoint is available and we have memory, we mark the interrupt endpoint as ready. */ + if (transfer_request -> ux_transfer_request_data_pointer != UX_NULL) + { + hid -> ux_host_class_hid_interrupt_endpoint_status = UX_HOST_CLASS_HID_INTERRUPT_ENDPOINT_READY; + status = UX_SUCCESS; + } + else + status = UX_MEMORY_INSUFFICIENT; + + /* Return completion status. */ + return(status); + } + + /* Check next endpoint. */ + endpoint = endpoint -> ux_endpoint_next_endpoint; + } + + /* Return error completion. */ + return(UX_ENDPOINT_HANDLE_UNKNOWN); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_item_data_get.c b/common/usbx_host_classes/src/ux_host_class_hid_item_data_get.c new file mode 100644 index 0000000..58bf853 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_item_data_get.c @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_item_data_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns a data from the descriptor based on its size, */ +/* format and whether it is signed or not. */ +/* */ +/* INPUT */ +/* */ +/* descriptor Pointer to descriptor */ +/* item Pointer to item */ +/* */ +/* OUTPUT */ +/* */ +/* ULONG data value */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_short_get Get 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_host_class_hid_item_data_get(UCHAR *descriptor, UX_HOST_CLASS_HID_ITEM *item) +{ + +ULONG value; + + + /* Get the length of the item. */ + switch (item -> ux_host_class_hid_item_report_length) + { + + case 1: + + value = (ULONG) *descriptor; + break; + + + case 2: + + value = (ULONG) _ux_utility_short_get(descriptor); + break; + + + case 4: + + value = (ULONG) _ux_utility_long_get(descriptor); + break; + + + default: + + return(0); + } + + /* Return the value. */ + return(value); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_activate.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_activate.c new file mode 100644 index 0000000..6712d00 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_activate.c @@ -0,0 +1,414 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Keyboard Client */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_keyboard.h" +#include "ux_host_stack.h" + +/* Define USB HID keyboard mapping tables. */ + +#ifndef UX_HOST_CLASS_HID_KEYBOARD_REGULAR_ARRAY_DEFAULT +#define UX_HOST_CLASS_HID_KEYBOARD_REGULAR_ARRAY_DEFAULT UX_HID_KEYBOARD_REGULAR_ARRAY_US +#endif +#ifndef UX_HOST_CLASS_HID_KEYBOARD_SHIFT_ARRAY_DEFAULT +#define UX_HOST_CLASS_HID_KEYBOARD_SHIFT_ARRAY_DEFAULT UX_HID_KEYBOARD_SHIFT_ARRAY_US +#endif +#ifndef UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_ON_ARRAY_DEFAULT +#define UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_ON_ARRAY_DEFAULT UX_HID_KEYBOARD_NUMLOCK_ON_ARRAY +#endif +#ifndef UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_OFF_ARRAY_DEFAULT +#define UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_OFF_ARRAY_DEFAULT UX_HID_KEYBOARD_NUMLOCK_OFF_ARRAY +#endif +#ifndef UX_HOST_CLASS_HID_KEYBOARD_KEYS_UPPER_RANGE_DEFAULT +#define UX_HOST_CLASS_HID_KEYBOARD_KEYS_UPPER_RANGE_DEFAULT UX_HID_KEYBOARD_KEYS_UPPER_RANGE +#endif +#ifndef UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_A_DEFAULT +#define UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_A_DEFAULT UX_HID_KEYBOARD_KEY_LETTER_A +#endif +#ifndef UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_Z_DEFAULT +#define UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_Z_DEFAULT UX_HID_KEYBOARD_KEY_LETTER_Z +#endif +#ifndef UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE_DEFAULT +#define UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE_DEFAULT UX_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE +#endif +#ifndef UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE_DEFAULT +#define UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE_DEFAULT UX_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE +#endif + +UCHAR ux_host_class_hid_keyboard_regular_array[] = +{ + UX_HOST_CLASS_HID_KEYBOARD_REGULAR_ARRAY_DEFAULT +}; + +UCHAR ux_host_class_hid_keyboard_shift_array[] = +{ + UX_HOST_CLASS_HID_KEYBOARD_SHIFT_ARRAY_DEFAULT +}; + +UCHAR ux_host_class_hid_keyboard_numlock_on_array[] = +{ + UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_ON_ARRAY_DEFAULT +}; + +UCHAR ux_host_class_hid_keyboard_numlock_off_array[] = +{ + UX_HOST_CLASS_HID_KEYBOARD_NUMLOCK_OFF_ARRAY_DEFAULT +}; + +UX_HOST_CLASS_HID_KEYBOARD_LAYOUT ux_host_class_hid_keyboard_layout = +{ + ux_host_class_hid_keyboard_regular_array, + ux_host_class_hid_keyboard_shift_array, + ux_host_class_hid_keyboard_numlock_on_array, + ux_host_class_hid_keyboard_numlock_off_array, + UX_HOST_CLASS_HID_KEYBOARD_KEYS_UPPER_RANGE_DEFAULT, + UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_A_DEFAULT, + UX_HOST_CLASS_HID_KEYBOARD_KEY_LETTER_Z_DEFAULT, + UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_LOWER_RANGE_DEFAULT, + UX_HOST_CLASS_HID_KEYBOARD_KEYS_KEYPAD_UPPER_RANGE_DEFAULT, +}; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_keyboard_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs the enumeration of a HID Keyboard Client. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_periodic_report_start */ +/* Start periodic report */ +/* _ux_host_class_hid_report_callback_register */ +/* Register callback */ +/* _ux_host_class_hid_report_id_get Get the report ID */ +/* _ux_host_class_hid_idle_set Set the idle rate */ +/* _ux_host_class_hid_report_set Do SET_REPORT */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_utility_thread_create Create thread */ +/* _ux_utility_thread_delete Delete thread */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_keyboard_activate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) +{ + +UX_HOST_CLASS_HID_REPORT_CALLBACK call_back; +UX_HOST_CLASS_HID_CLIENT_REPORT client_report; +UX_HOST_CLASS_HID_REPORT_GET_ID report_id; +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT *hid_client; +UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance; +ULONG event_process_memory_size; +UINT status = UX_SUCCESS; +#ifdef UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE +UX_HOST_CLASS_HID_FIELD *field; +#endif + + + /* Get the instance to the HID class. */ + hid = command -> ux_host_class_hid_client_command_instance; + + /* And of the HID client. */ + hid_client = hid -> ux_host_class_hid_client; + + /* Get some memory for both the HID class instance of this client + and for the callback. */ + keyboard_instance = (UX_HOST_CLASS_HID_KEYBOARD *) _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, + sizeof(UX_HOST_CLASS_HID_KEYBOARD)); + if (keyboard_instance == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Attach the remote control instance to the client instance. */ + hid_client -> ux_host_class_hid_client_local_instance = (VOID *) keyboard_instance; + + /* Save the HID instance in the client instance. */ + keyboard_instance -> ux_host_class_hid_keyboard_hid = hid; + + /* The instance is live now. */ + keyboard_instance -> ux_host_class_hid_keyboard_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* Allocate the round-robin buffer that the remote control instance will use + * to store the usages as they come in. + * Size calculation overflow is checked near where _USAGE_ARRAY_LENGTH is defined. + */ + keyboard_instance -> ux_host_class_hid_keyboard_usage_array = (ULONG *) + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH*4); + if (keyboard_instance -> ux_host_class_hid_keyboard_usage_array == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + + /* Initialize the head and tail of this array. */ + keyboard_instance -> ux_host_class_hid_keyboard_usage_array_head = keyboard_instance -> ux_host_class_hid_keyboard_usage_array; + keyboard_instance -> ux_host_class_hid_keyboard_usage_array_tail = keyboard_instance -> ux_host_class_hid_keyboard_usage_array; + + /* Get the report ID for the keyboard. The keyboard is a INPUT report. + This should be 0 but in case. */ + report_id.ux_host_class_hid_report_get_report = UX_NULL; + report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT; + status = _ux_host_class_hid_report_id_get(hid, &report_id); + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + + /* Save the keyboard report ID. */ + keyboard_instance -> ux_host_class_hid_keyboard_id = (USHORT)(report_id.ux_host_class_hid_report_get_id); + + /* Set the idle rate of the keyboard to 0. This way a report is generated only when there is an activity. */ + status = _ux_host_class_hid_idle_set(hid, 0, keyboard_instance -> ux_host_class_hid_keyboard_id); + } + } + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + +#ifdef UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE + + /* Summarize number of usages to allocate state buffer for keyboard report. + We reserve 3 bits for lock status, 8 bits for modifier status. + We get number of keys from report of 8-bit array. + Key usages bytes then saved if it's down. + - 3 Locks - 8 Modifiers - N regular keys ... + */ + keyboard_instance -> ux_host_class_hid_keyboard_key_count = 3 + 8; + field = report_id.ux_host_class_hid_report_get_report -> ux_host_class_hid_report_field; + while(field) + { + if (field -> ux_host_class_hid_field_report_size == 8) + keyboard_instance -> ux_host_class_hid_keyboard_key_count += field -> ux_host_class_hid_field_report_count; + field = field -> ux_host_class_hid_field_next_field; + } + + /* Process memory includes: + - states for last [usage, value] and new [usage, value], (2 * 2) * max number of keys to log + - actions for last and new buffers, 2 * max number of keys to log + */ + UX_UTILITY_MULC_SAFE(keyboard_instance -> ux_host_class_hid_keyboard_key_count, 6, event_process_memory_size, status); + + /* Calculation overflow check. */ + if (status != UX_SUCCESS) + return(status); +#else + + /* We reserve 3 bytes for lock keys, 3 for processing. */ + keyboard_instance -> ux_host_class_hid_keyboard_key_count = 3; + + /* key count 3, multiply 2 is int safe. */ + event_process_memory_size = keyboard_instance -> ux_host_class_hid_keyboard_key_count * 2; +#endif + + /* Allocate memory for usages states. */ + keyboard_instance -> ux_host_class_hid_keyboard_key_state = (UCHAR *) + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, event_process_memory_size); + if (keyboard_instance -> ux_host_class_hid_keyboard_key_state == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + + /* Initialize the report callback. */ + call_back.ux_host_class_hid_report_callback_id = keyboard_instance -> ux_host_class_hid_keyboard_id; + call_back.ux_host_class_hid_report_callback_function = _ux_host_class_hid_keyboard_callback; + call_back.ux_host_class_hid_report_callback_buffer = UX_NULL; + call_back.ux_host_class_hid_report_callback_flags = UX_HOST_CLASS_HID_REPORT_DECOMPRESSED; + call_back.ux_host_class_hid_report_callback_length = 0; + + /* Register the report call back when data comes it on this report. */ + status = _ux_host_class_hid_report_callback_register(hid, &call_back); + } + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + + /* We need a semaphore now. This will be used to synchronize the HID report with the keyboard thread. */ + status = _ux_utility_semaphore_create(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore, "ux_host_class_hid_keyboard_semaphore", 0); + if(status != UX_SUCCESS) + status = (UX_SEMAPHORE_ERROR); + } + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + + /* The HID Keyboard needs a Thread to process LED changes. This process is asynchronous + to the callback because it involves using the commands on the Control Pipe which cannot + be done during callbacks. First allocate some stack memory. */ + keyboard_instance -> ux_host_class_hid_keyboard_thread_stack = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_THREAD_STACK_SIZE); + + /* Check if stack memory was allocated. */ + if (keyboard_instance -> ux_host_class_hid_keyboard_thread_stack == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + } + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + + /* Then create the actual thread. */ + status = _ux_utility_thread_create(&keyboard_instance -> ux_host_class_hid_keyboard_thread, "ux_host_stack_keyboard_thread",_ux_host_class_hid_keyboard_thread, + (ULONG) (ALIGN_TYPE) keyboard_instance, keyboard_instance -> ux_host_class_hid_keyboard_thread_stack, + UX_THREAD_STACK_SIZE, UX_THREAD_PRIORITY_KEYBOARD, + UX_THREAD_PRIORITY_KEYBOARD, UX_NO_TIME_SLICE, TX_AUTO_START); + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + + UX_THREAD_EXTENSION_PTR_SET(&(keyboard_instance -> ux_host_class_hid_keyboard_thread), keyboard_instance) + + /* Default state of keyboard is with NumLock on. */ + keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= UX_HID_KEYBOARD_STATE_NUM_LOCK; + + /* We need to build the field for the LEDs. */ + keyboard_instance -> ux_host_class_hid_keyboard_led_mask = keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & + UX_HID_KEYBOARD_STATE_MASK_LOCK; + + /* We need to find the OUTPUT report for the keyboard LEDs. */ + report_id.ux_host_class_hid_report_get_report = UX_NULL; + report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_OUTPUT; + status = _ux_host_class_hid_report_id_get(hid, &report_id); + + /* The report ID should exist. If there is an error, we do not proceed. */ + if (status == UX_SUCCESS) + { + + /* Memorize the report pointer. */ + client_report.ux_host_class_hid_client_report = report_id.ux_host_class_hid_report_get_report; + + /* The report set is raw since the LEDs mask is already in the right format. */ + client_report.ux_host_class_hid_client_report_flags = UX_HOST_CLASS_HID_REPORT_RAW; + + /* The length of this report is 1 byte. */ + client_report.ux_host_class_hid_client_report_length = 1; + + /* The output report buffer is the LED mask field. */ + client_report.ux_host_class_hid_client_report_buffer = &keyboard_instance -> ux_host_class_hid_keyboard_led_mask; + + /* The HID class will perform the SET_REPORT command. Do not check for error here, this is + handled by the function itself. */ + status = _ux_host_class_hid_report_set(hid, &client_report); + } + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + + /* Initialize the keyboard layout and use it to decode keys. */ + keyboard_instance -> ux_host_class_hid_keyboard_layout = &ux_host_class_hid_keyboard_layout; + keyboard_instance -> ux_host_class_hid_keyboard_keys_decode_disable = UX_FALSE; + + /* Start the periodic report. */ + status = _ux_host_class_hid_periodic_report_start(hid); + } + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_HID_CLIENT_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid_client); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_KEYBOARD_ACTIVATE, hid, keyboard_instance, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Return completion status. */ + return(status); + } + + /* There is error, delete thread. */ + _ux_utility_thread_delete(&keyboard_instance -> ux_host_class_hid_keyboard_thread); + } + + /* We are here if there is error. */ + + /* Detach instance. */ + hid_client -> ux_host_class_hid_client_local_instance = UX_NULL; + + /* Free usage state. */ + if (keyboard_instance -> ux_host_class_hid_keyboard_key_state) + _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_key_state); + + /* Free stack. */ + if (keyboard_instance -> ux_host_class_hid_keyboard_thread_stack) + _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_thread_stack); + + /* Delete semaphore. */ + if (keyboard_instance -> ux_host_class_hid_keyboard_semaphore.tx_semaphore_id != TX_EMPTY) + _ux_utility_semaphore_delete(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore); + + /* Free usage array. */ + if (keyboard_instance -> ux_host_class_hid_keyboard_usage_array) + _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_usage_array); + + /* Free instance. */ + _ux_utility_memory_free(keyboard_instance); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_callback.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_callback.c new file mode 100644 index 0000000..a9dedbd --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_callback.c @@ -0,0 +1,570 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Keyboard Client */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_keyboard.h" +#include "ux_host_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_keyboard_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the callback mechanism for a report registration. */ +/* */ +/* INPUT */ +/* */ +/* callback Pointer to callback */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_set Set memory */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class when a report is generated */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hid_keyboard_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK *callback) +{ + +/* This array contains the bit for each alternate key (modifier or lock key) + that we report to the application. For example, if you wanted to set the + bit for the CAPS_LOCK key, you would do: + keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= alternate_key_bits[0]; + Index 0 is used since it corresponds to the CAPS_LOCK bit in the array. Note + that _alternate_key_state is what we report to the application. */ +const ULONG alternate_key_bits[] = { + UX_HID_KEYBOARD_STATE_CAPS_LOCK, + UX_HID_KEYBOARD_STATE_NUM_LOCK, + UX_HID_KEYBOARD_STATE_SCROLL_LOCK, + UX_HID_KEYBOARD_STATE_LEFT_CTRL, + UX_HID_KEYBOARD_STATE_LEFT_SHIFT, + UX_HID_KEYBOARD_STATE_LEFT_ALT, + UX_HID_KEYBOARD_STATE_LEFT_GUI, + UX_HID_KEYBOARD_STATE_RIGHT_CTRL, + UX_HID_KEYBOARD_STATE_RIGHT_SHIFT, + UX_HID_KEYBOARD_STATE_RIGHT_ALT, + UX_HID_KEYBOARD_STATE_RIGHT_GUI, +}; + +/* Define the indices for each alternate key in the alternate key bits array. */ + +#define ALTERNATE_KEY_BITS_IDX_CAPS_LOCK ( 0) +#define ALTERNATE_KEY_BITS_IDX_NUM_LOCK ( 1) +#define ALTERNATE_KEY_BITS_IDX_SCROLL_LOCK ( 2) + +#define ALTERNATE_KEY_BITS_IDX_LEFT_CTRL ( 3) +#define ALTERNATE_KEY_BITS_IDX_LEFT_SHIFT ( 4) +#define ALTERNATE_KEY_BITS_IDX_LEFT_ALT ( 5) +#define ALTERNATE_KEY_BITS_IDX_LEFT_GUI ( 6) +#define ALTERNATE_KEY_BITS_IDX_RIGHT_CTRL ( 7) +#define ALTERNATE_KEY_BITS_IDX_RIGHT_SHIFT ( 8) +#define ALTERNATE_KEY_BITS_IDX_RIGHT_ALT ( 9) +#define ALTERNATE_KEY_BITS_IDX_RIGHT_GUI (10) + +/* Define a macro to get the index of a modifier key in the alternate key bits array. */ +#define GET_ALTERNATE_KEY_BITS_IDX(usage) ((usage) - UX_HID_MODIFIER_KEY_LEFT_CONTROL + ALTERNATE_KEY_BITS_IDX_LEFT_CTRL) + +/* Define key states. */ +#define KEY_STATE_REGULAR (11) +#define KEY_STATE_NO_KEY (12) + +#define KEY_UP ( 0) +#define KEY_KEEP ( 1) +#define KEY_DOWN ( 2) +#define KEY_DEL ( 3) + + +UX_HOST_CLASS_HID_CLIENT *hid_client; +UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance; +UX_HOST_CLASS_HID_KEYBOARD_LAYOUT *keyboard_layout; +UCHAR *keypad_array; +ULONG *array_head; +ULONG *array_tail; +ULONG *array_end; +ULONG *array_start; +ULONG *report_buffer; +ULONG *report_buffer_end; +ULONG keyboard_char = 0; +ULONG shift_on; +ULONG capslock_on; +ULONG numlock_on; +ULONG key_usage; +ULONG key_value; + +/* This variable either contains an index into the alternate key bit array, + or a value that describes the current key i.e. regular key or no key. */ +UINT key_state; + +#if !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) +UCHAR *previous_lock_key_states; +UCHAR *current_lock_key_states; +#else +UINT i, i_save, new_count; +UCHAR *state_usage; +UCHAR *state_value; +UCHAR *state_action; +#endif + + + /* Get the HID client instance that issued the callback. */ + hid_client = callback -> ux_host_class_hid_report_callback_client; + + /* Get the keyboard local instance. */ + keyboard_instance = (UX_HOST_CLASS_HID_KEYBOARD *) hid_client -> ux_host_class_hid_client_local_instance; + + /* Get the report buffer. */ + report_buffer = (ULONG *)callback -> ux_host_class_hid_report_callback_buffer; + + /* Get the end of report buffer. */ + report_buffer_end = &report_buffer[callback -> ux_host_class_hid_report_callback_actual_length]; + +#if !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) + + /* Get the previous states of the lock keys. */ + previous_lock_key_states = &keyboard_instance -> ux_host_class_hid_keyboard_key_state[0]; + + /* Get the current states of the lock keys and immediately initialize them to zero; + if a lock key is not pressed in this report, it will remain zero (not pressed). */ + current_lock_key_states = &keyboard_instance -> ux_host_class_hid_keyboard_key_state[3]; + _ux_utility_memory_set(current_lock_key_states, 0, 3); + + /* Scan the report buffer and decode it. */ + while(report_buffer < report_buffer_end) + { + + /* Get usage and value from buffer. */ + key_usage = *report_buffer ++; + key_value = *report_buffer ++; + + /* Analyze the usage we have received. We eliminate the page from the usage. */ + key_usage &= 0xFF; +#else + + /* Initialize key states for report processing. */ + state_usage = keyboard_instance -> ux_host_class_hid_keyboard_key_state; + state_value = state_usage + keyboard_instance -> ux_host_class_hid_keyboard_key_count * 2; + state_action = state_value + keyboard_instance -> ux_host_class_hid_keyboard_key_count * 2; + + /* Reset state actions to DEL(not received). */ + _ux_utility_memory_set(state_usage + keyboard_instance -> ux_host_class_hid_keyboard_key_count, 0, keyboard_instance -> ux_host_class_hid_keyboard_key_count); + _ux_utility_memory_set(state_value + keyboard_instance -> ux_host_class_hid_keyboard_key_count, 0, keyboard_instance -> ux_host_class_hid_keyboard_key_count); + _ux_utility_memory_set(state_action, KEY_DEL, keyboard_instance -> ux_host_class_hid_keyboard_key_count * 2); + + new_count = keyboard_instance -> ux_host_class_hid_keyboard_key_count; + while(report_buffer < report_buffer_end) + { + + /* Get usage and value from buffer. */ + key_usage = *report_buffer ++; + key_value = *report_buffer ++; + + /* Analyze the usage we have received. We eliminate the page from the usage. */ + key_usage &= 0xFF; + key_value &= 0xFF; + + /* If there is no key or in phantom state (roll over), skip. */ + if (key_usage <= UX_HID_KEYBOARD_PHANTOM_STATE) + continue; + + /* Check if the key is previously reported. */ + for (i = 0; i < keyboard_instance -> ux_host_class_hid_keyboard_key_count; i ++) + { + + /* Check if it's modified. */ + if (state_usage[i] == key_usage) + { + + /* Replace action state. */ + state_action[i] = (state_value[i] == key_value) ? KEY_KEEP : (key_value ? KEY_DOWN : KEY_UP); + + /* Replace key value. */ + state_value[i] = key_value; + break; + } + } + + /* When there is new key, add to new key list. */ + if (i == keyboard_instance -> ux_host_class_hid_keyboard_key_count) + { + + /* Add key value. */ + state_usage [new_count] = key_usage; + state_value [new_count] = key_value; + + /* Add key action. */ + state_action[new_count] = key_value ? KEY_DOWN : KEY_KEEP; + + new_count ++; + } + } /* while(report_buffer < report_buffer_end) */ + + /* Process pending key states. */ + i_save = 0; + for (i = 0; i < new_count; i ++) + { + + /* Get state value from buffer. */ + key_usage = state_usage[i]; + key_value = state_value[i]; + key_state = state_action[i]; + + /* If no key, just skip. */ + if (key_usage == 0) + continue; + + /* If key not reported, add up event if it's enabled. */ + if (key_state == KEY_DEL) + { + + /* Clear state, do not save. */ + state_usage[i] = 0; + state_action[i] = KEY_UP; + } + + /* Key reported, process it. */ + else + { + + /* We need to save key anyway. */ + if (i_save < i) + { + state_usage[i_save] = key_usage; + state_value[i_save] = key_value; + } + i_save ++; + } + + /* Skip keep keys. */ + if (state_action[i] == KEY_KEEP) + continue; + + /* Now handle key event. */ + keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state &= ~(UX_HID_KEYBOARD_STATE_FUNCTION | UX_HID_KEYBOARD_STATE_KEY_UP); +#endif /* UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE */ + + /* Determine what key this is. */ + switch(key_usage) + { + + /* This is the usage of a modifier key. Set or clear the appropriate + bits in the alternate key state bitmap. */ + case UX_HID_MODIFIER_KEY_LEFT_SHIFT : + case UX_HID_MODIFIER_KEY_RIGHT_SHIFT : + case UX_HID_MODIFIER_KEY_LEFT_ALT : + case UX_HID_MODIFIER_KEY_RIGHT_ALT : + case UX_HID_MODIFIER_KEY_RIGHT_CONTROL : + case UX_HID_MODIFIER_KEY_LEFT_CONTROL : + case UX_HID_MODIFIER_KEY_RIGHT_GUI : + case UX_HID_MODIFIER_KEY_LEFT_GUI : + + key_state = GET_ALTERNATE_KEY_BITS_IDX(key_usage); + + /* We have received a modifier Key. Remember the state. */ + if (key_value > 0) + keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= alternate_key_bits[key_state]; + else + keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state &= ~alternate_key_bits[key_state]; + + break; + + /* This is the usage of a LOCK key. Just save the its index in the alternate + key bit array. */ + + case UX_HID_LED_KEY_CAPS_LOCK : + key_state = ALTERNATE_KEY_BITS_IDX_CAPS_LOCK; + break; + + case UX_HID_LED_KEY_NUM_LOCK : + key_state = ALTERNATE_KEY_BITS_IDX_NUM_LOCK; + break; + + case UX_HID_LED_KEY_SCROLL_LOCK : + key_state = ALTERNATE_KEY_BITS_IDX_SCROLL_LOCK; + break; + +#if !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) + + /* Usage no key. */ + case UX_HID_KEYBOARD_NO_KEY : + case UX_HID_KEYBOARD_PHANTOM_STATE : + key_state = KEY_STATE_NO_KEY; + break; +#endif + + /* This is the usage of a regular key. Here, we just get the decoded + value; we will add it to the queue later. */ + default : + + /* By default the key will be saved. */ + key_state = KEY_STATE_REGULAR; + + /* Skip decode if decode is disabled. */ + if (keyboard_instance -> ux_host_class_hid_keyboard_keys_decode_disable == UX_TRUE) + { + + /* Use raw data (scan code) as key code. */ + keyboard_char = key_value; + break; + } + + /* Get keyboard layout instance. */ + keyboard_layout = keyboard_instance -> ux_host_class_hid_keyboard_layout; + + /* Is this key outside the valid range? */ + if (key_value > keyboard_layout -> ux_host_class_hid_keyboard_layout_keys_upper_range) + { + + /* Set a flag to discard it. */ + key_state = KEY_STATE_NO_KEY; + break; + } + + /* We have received a regular key. Depending on the state of the shift or numlock status, the key should be mapped into + one of the translation tables. We verify if the key is within our mapping range. */ + + /* Get SHIFT, CAPS_LOCK and NUM_LOCK states. */ + shift_on = (keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & UX_HID_KEYBOARD_STATE_SHIFT) ? UX_TRUE : UX_FALSE; + capslock_on = (keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & UX_HID_KEYBOARD_STATE_CAPS_LOCK) ? UX_TRUE : UX_FALSE; + numlock_on = (keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & UX_HID_KEYBOARD_STATE_NUM_LOCK) ? UX_TRUE : UX_FALSE; + + /* Check if we have letters ('a' to 'z'). */ + if (key_value >= keyboard_layout -> ux_host_class_hid_keyboard_layout_letters_lower_range && + key_value <= keyboard_layout -> ux_host_class_hid_keyboard_layout_letters_upper_range) + { + + /* We have letters, check the Shift and CapsLock state. */ + if (shift_on != capslock_on) + + /* Shift and CapsLock in different state: upper case. */ + keyboard_char = keyboard_layout -> ux_host_class_hid_keyboard_layout_shift_array[key_value]; + else + + /* Lower case. */ + keyboard_char = keyboard_layout -> ux_host_class_hid_keyboard_layout_regular_array[key_value]; + + break; /* default: */ + } + + /* Check if we have received a keypad key. They may be multiplexed. */ + if (key_value >= keyboard_layout -> ux_host_class_hid_keyboard_layout_keypad_lower_range && + key_value <= keyboard_layout -> ux_host_class_hid_keyboard_layout_keypad_upper_range) + { + + /* We have a keypad key. Check the NumLock state. */ + if (numlock_on) + + /* Numlock is on. */ + keypad_array = keyboard_layout -> ux_host_class_hid_keyboard_layout_numlock_on_array; + + else + + /* Numlock is off. */ + keypad_array = keyboard_layout -> ux_host_class_hid_keyboard_layout_numlock_off_array; + + /* Decode the keypad key. */ + keyboard_char = keypad_array[key_value - + keyboard_layout -> ux_host_class_hid_keyboard_layout_keypad_lower_range]; + + break; /* default: */ + } + + /* Check the state of the shift. */ + if (shift_on) + + /* We get the key from the shifted array. */ + keyboard_char = keyboard_layout -> ux_host_class_hid_keyboard_layout_shift_array[key_value]; + + else + + /* We get the key from the regular array. */ + keyboard_char = keyboard_layout -> ux_host_class_hid_keyboard_layout_regular_array[key_value]; + + break; /* default: */ + + } /* switch(key_usage) */ + +#if defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) + + if (state_action[i] == KEY_UP) + +#if defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_KEY_DOWN_ONLY) + + /* Skip save. */ + continue; +#else + + /* Save key up state. */ + keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= UX_HID_KEYBOARD_STATE_KEY_UP; +#endif +#endif + + /* If there is no key, just try next. */ + if (key_state == KEY_STATE_NO_KEY) + continue; + + /* Is this a LOCK key (i.e. caps lock, scroll lock or num lock)? */ + if (key_state <= ALTERNATE_KEY_BITS_IDX_SCROLL_LOCK) + { + + /* Skip decode if decode is disabled. */ + if (keyboard_instance -> ux_host_class_hid_keyboard_keys_decode_disable == UX_TRUE) + { + + /* Use raw data (scan code) as key code. */ + keyboard_char = key_value; + } + else + { + +#if !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) + + /* Reflect the press in the current lock key state. */ + current_lock_key_states[key_state] = (UCHAR)key_value; + + /* Take action only if key state changes from up to down (pressed). + Remember that the nothing happens when lock keys are released. */ + if (previous_lock_key_states[key_state] == 0) +#elif !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_KEY_DOWN_ONLY) + + /* Take action only if key state changes from up to down (pressed). */ + if (state_action[i] == KEY_DOWN) +#endif + { + + /* Reflect the change in the keyboard state. The state should be inverted. */ + if (keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & alternate_key_bits[key_state]) + keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state &= (ULONG)~alternate_key_bits[key_state]; + else + keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= alternate_key_bits[key_state]; + + /* Wake up the keyboard thread semaphore. */ + _ux_utility_semaphore_put(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore); + } + +#if defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) && defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_LOCK_KEYS) + + /* Use usage and UX_HID_KEYBOARD_STATE_FUNCTION. */ + keyboard_char = key_usage; + keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= UX_HID_KEYBOARD_STATE_FUNCTION; + +#else + + /* Check next usage & value. */ + continue; +#endif + } + } + + /* If it's modifier, check next usage & value. */ + else if (key_state < KEY_STATE_REGULAR) + { +#if defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) && defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE_REPORT_MODIFIER_KEYS) + + /* Use usage and UX_HID_KEYBOARD_STATE_FUNCTION. */ + keyboard_char = key_usage; + keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state |= UX_HID_KEYBOARD_STATE_FUNCTION; +#else + + /* Check next usage & value. */ + continue; +#endif + } + + /* If we get here, then we have a regular key. Now it's time to save + raw/decoded key in the key queue. */ + + /* This key should now be inserted in the circular array for the application to retrieve it. */ + array_start = keyboard_instance -> ux_host_class_hid_keyboard_usage_array; + array_end = array_start + UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH; + array_head = keyboard_instance -> ux_host_class_hid_keyboard_usage_array_head; + array_tail = keyboard_instance -> ux_host_class_hid_keyboard_usage_array_tail; + + /* We have a single usage/value. We have to store it into the array. If the array overflows, + there is no mechanism for flow control here so we ignore the usage/value until the + applications makes more room in the array. */ + + /* Is the head at the end of the array and need to loop back? */ + if ((array_head + 2) >= array_end) + array_head = array_start; + else + array_head += 2; + + /* Do we have enough space to store the new usage? */ + if (array_head != array_tail) + { + + /* Yes, we have some space. */ + *keyboard_instance -> ux_host_class_hid_keyboard_usage_array_head = keyboard_char; + *(keyboard_instance -> ux_host_class_hid_keyboard_usage_array_head + 1) = keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state; + + /* Now update the array head. */ + keyboard_instance -> ux_host_class_hid_keyboard_usage_array_head = array_head; + } + else + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + + } /* while(report_buffer < report_buffer_end) */ + +#if !defined(UX_HOST_CLASS_HID_KEYBOARD_EVENTS_KEY_CHANGES_MODE) + + /* Copy the current lock key states to the previous states. Note that if + a lock key wasn't down in this report, its current state would have + remained zero (not pressed). */ + _ux_utility_memory_copy(previous_lock_key_states, current_lock_key_states, 3); +#else + + /* Clear redundant data after last saved key. */ + _ux_utility_memory_set(state_usage + i_save, 0, keyboard_instance -> ux_host_class_hid_keyboard_key_count - i_save); +#endif + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_deactivate.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_deactivate.c new file mode 100644 index 0000000..968cbd2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_deactivate.c @@ -0,0 +1,129 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Keyboard Client */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_keyboard.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_keyboard_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs the deactivation of a HID Keyboard Client. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_periodic_report_stop */ +/* Stop periodic report */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_utility_thread_delete Delete thread */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_keyboard_deactivate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) +{ + +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT *hid_client; +UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance; +UINT status; + + + /* Get the instance to the HID class. */ + hid = command -> ux_host_class_hid_client_command_instance; + + /* Stop the periodic report. */ + status = _ux_host_class_hid_periodic_report_stop(hid); + + /* Get the HID client pointer. */ + hid_client = hid -> ux_host_class_hid_client; + + /* Get the remote control local instance. */ + keyboard_instance = (UX_HOST_CLASS_HID_KEYBOARD *) hid_client -> ux_host_class_hid_client_local_instance; + + /* Stop the semaphore. */ + status = _ux_utility_semaphore_delete(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore); + + /* Free memory for key states. */ + _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_key_state); + + /* Terminate the thread. */ + _ux_utility_thread_delete(&keyboard_instance -> ux_host_class_hid_keyboard_thread); + + /* Return to the pool the thread stack. */ + _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_thread_stack); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_KEYBOARD_DEACTIVATE, hid, keyboard_instance, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Unload all the memory used by the keyboard client. */ + _ux_utility_memory_free(keyboard_instance -> ux_host_class_hid_keyboard_usage_array); + + /* Now free the instance memory. */ + _ux_utility_memory_free(hid_client -> ux_host_class_hid_client_local_instance); + + /* We may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_HID_CLIENT_REMOVAL, hid -> ux_host_class_hid_class, (VOID *) hid_client); + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_entry.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_entry.c new file mode 100644 index 0000000..ae9e4c6 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_entry.c @@ -0,0 +1,121 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Keyboard Client */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_keyboard.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_keyboard_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the HID keyboard client. */ +/* This function is called by the HID class after it has parsed a new */ +/* HID report descriptor and is searching for a HID client. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_keyboard_activate */ +/* Activate HID keyboard */ +/* _ux_host_class_hid_keyboard_deactivate */ +/* Deactivate HID keyboard */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_keyboard_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_hid_client_command_request) + { + + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the HID class know if we want to own + this device or not */ + if ((command -> ux_host_class_hid_client_command_page == UX_HOST_CLASS_HID_PAGE_GENERIC_DESKTOP_CONTROLS) && + (command -> ux_host_class_hid_client_command_usage == UX_HOST_CLASS_HID_GENERIC_DESKTOP_KEYBOARD)) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used by the HID class to start the HID client. */ + status = _ux_host_class_hid_keyboard_activate(command); + + /* Return completion status. */ + return(status); + + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used by the HID class when it received a deactivate + command from the USBX stack and there was a HID client attached to the HID instance */ + status = _ux_host_class_hid_keyboard_deactivate(command); + + /* Return completion status. */ + return(status); + } + + /* Return error status. */ + return(UX_ERROR); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_ioctl.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_ioctl.c new file mode 100644 index 0000000..5a7574e --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_ioctl.c @@ -0,0 +1,124 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Keyboard Client */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_keyboard.h" +#include "ux_host_stack.h" + +extern UX_HOST_CLASS_HID_KEYBOARD_LAYOUT ux_host_class_hid_keyboard_layout; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_keyboard_ioctl PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the ioctl entry point for the application to */ +/* configure the HID keyboard device. */ +/* */ +/* INPUT */ +/* */ +/* keyboard_instance Pointer to hid keyboard */ +/* ioctl_function ioctl function */ +/* parameter pointer to parameter/structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* HID Keyboard Client */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_keyboard_ioctl(UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance, + ULONG ioctl_function, VOID *parameter) +{ + +UINT status = UX_SUCCESS; + + + switch(ioctl_function) + { + + case UX_HID_KEYBOARD_IOCTL_SET_LAYOUT: + + /* Change the keyboard layout setting. */ + keyboard_instance -> ux_host_class_hid_keyboard_layout = (parameter == UX_NULL) ? + &ux_host_class_hid_keyboard_layout : + (UX_HOST_CLASS_HID_KEYBOARD_LAYOUT *) parameter; + + break; + + case UX_HID_KEYBOARD_IOCTL_DISABLE_KEYS_DECODE: + + /* Disable the keys decode setting. */ + keyboard_instance -> ux_host_class_hid_keyboard_keys_decode_disable = UX_TRUE; + + break; + + case UX_HID_KEYBOARD_IOCTL_ENABLE_KEYS_DECODE: + + /* Enable the keys decode setting. */ + keyboard_instance -> ux_host_class_hid_keyboard_keys_decode_disable = UX_FALSE; + + break; + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Function not supported. Return an error. */ + status = UX_FUNCTION_NOT_SUPPORTED; + + } + + /* Return status to caller. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_key_get.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_key_get.c new file mode 100644 index 0000000..0e02029 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_key_get.c @@ -0,0 +1,123 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Remote Control Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_keyboard.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_keyboard_key_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads the key and keyboard state from the */ +/* round-robin buffer. */ +/* */ +/* INPUT */ +/* */ +/* keyboard_instance Pointer to remote control */ +/* keyboard key Pointer to keyboard key */ +/* keyboard state Pointer to keyboard state */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance */ +/* */ +/* CALLED BY */ +/* */ +/* User application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_keyboard_key_get(UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance, + ULONG *keyboard_key, ULONG *keyboard_state) +{ + +ULONG *array_head; +ULONG *array_tail; +ULONG *array_end; +ULONG *array_start; +UX_HOST_CLASS_HID *hid; + + /* Get the HID class associated with the HID client. */ + hid = keyboard_instance -> ux_host_class_hid_keyboard_hid; + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Load the keyboard key and state from the usage array . */ + array_start = keyboard_instance -> ux_host_class_hid_keyboard_usage_array; + array_end = array_start + UX_HOST_CLASS_HID_KEYBOARD_USAGE_ARRAY_LENGTH; + array_head = keyboard_instance -> ux_host_class_hid_keyboard_usage_array_head; + array_tail = keyboard_instance -> ux_host_class_hid_keyboard_usage_array_tail; + + /* We want to extract a usage/value from the circular queue of the keyboard instance. */ + if (array_tail == array_head) + return(UX_ERROR); + + /* Get the usage/value from the current tail. */ + *keyboard_key = *array_tail; + *keyboard_state = *(array_tail + 1); + + /* Now we need to update the tail value. Are we at the end of the array? */ + if ((array_tail+2) >= array_end) + array_tail = array_start; + else + array_tail+=2; + + /* Set the tail pointer. */ + keyboard_instance -> ux_host_class_hid_keyboard_usage_array_tail = array_tail; + + /* The status will tell the application there is something valid in the key/state. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_keyboard_thread.c b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_thread.c new file mode 100644 index 0000000..fbd52e7 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_keyboard_thread.c @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Keyboard Client */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_keyboard.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_keyboard_thread PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains the keyboard thread used to process the changes */ +/* in the keyboard LEDs. */ +/* */ +/* INPUT */ +/* */ +/* keyboard_instance The keyboard instance for */ +/* there was a change in LEDs */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_semaphore_get Get signal semaphore */ +/* _ux_host_class_hid_report_id_get Get report ID */ +/* _ux_host_class_hid_report_set Do SET_REPORT */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hid_keyboard_thread(ULONG thread_input) +{ +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT_REPORT client_report; +UX_HOST_CLASS_HID_REPORT_GET_ID report_id; +UINT status; +UX_HOST_CLASS_HID_KEYBOARD *keyboard_instance; + + /* Cast the thread_input variable into the proper format. */ + UX_THREAD_EXTENSION_PTR_GET(keyboard_instance, UX_HOST_CLASS_HID_KEYBOARD, thread_input) + + /* Loop forever waiting for changes signaled through the semaphore. */ + while (1) + { + + /* Wait for the semaphore to be put by the root hub or a regular hub. */ + status = _ux_utility_semaphore_get(&keyboard_instance -> ux_host_class_hid_keyboard_semaphore, UX_WAIT_FOREVER); + + /* The semaphore could be awaken because the semaphore was destroyed by the HID client + when the keyboard is removed. */ + if (status == UX_SUCCESS) + { + + /* We got awaken by the keyboard callback which indicates a change on the LEDs has to happen. + We need to build the field for the leds. */ + keyboard_instance -> ux_host_class_hid_keyboard_led_mask = keyboard_instance -> ux_host_class_hid_keyboard_alternate_key_state & + UX_HID_KEYBOARD_STATE_MASK_LOCK; + + /* Recall the HID instance for this client. */ + hid = keyboard_instance -> ux_host_class_hid_keyboard_hid; + + /* We need to find the OUTPUT report for the keyboard LEDs. */ + report_id.ux_host_class_hid_report_get_report = UX_NULL; + report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_OUTPUT; + status = _ux_host_class_hid_report_id_get(hid, &report_id); + + /* The report ID should exist. If there is an error, we do not proceed. */ + if (status == UX_SUCCESS) + { + + /* Memorize the report pointer. */ + client_report.ux_host_class_hid_client_report = report_id.ux_host_class_hid_report_get_report; + + /* The report set is raw since the LEDs mask is already in the right format. */ + client_report.ux_host_class_hid_client_report_flags = UX_HOST_CLASS_HID_REPORT_RAW; + + /* The length of this report is 1 byte. */ + client_report.ux_host_class_hid_client_report_length = 1; + + /* The output report buffer is the LED mask field. */ + client_report.ux_host_class_hid_client_report_buffer = &keyboard_instance -> ux_host_class_hid_keyboard_led_mask; + + /* The HID class will perform the SET_REPORT command. */ + _ux_host_class_hid_report_set(hid, &client_report); + } + } + else + + /* The thread should terminate upon a semaphore error. */ + return; + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_local_item_parse.c b/common/usbx_host_classes/src/ux_host_class_hid_local_item_parse.c new file mode 100644 index 0000000..16677de --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_local_item_parse.c @@ -0,0 +1,250 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_local_item_parse PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses a local item from the report descriptor. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* item Pointer to item */ +/* descriptor Pointer to descriptor */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_item_data_get Get data item */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_local_item_parse(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_ITEM *item, UCHAR *descriptor) +{ + +UX_HOST_CLASS_HID_PARSER *hid_parser; +ULONG usage; +ULONG usage_min; +ULONG usage_max; +ULONG delimiter_set; + + /* Get the temporary parser structure pointer. */ + hid_parser = &hid -> ux_host_class_hid_parser; + + /* Analyze the tag. */ + switch (item -> ux_host_class_hid_item_report_tag) + { + + case UX_HOST_CLASS_HID_LOCAL_TAG_USAGE: + + /* Local usage tag, check if we have an overflow. */ + if (hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage == UX_HOST_CLASS_HID_USAGES) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_USAGE_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_USAGE_OVERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_USAGE_OVERFLOW); + } + + /* Obtain the usage from the descriptor. */ + usage = _ux_host_class_hid_item_data_get(descriptor, item); + + /* Combine the global usage with the local usage to form a unique usage ID. */ + usage |= (hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_usage_page << 16); + + /* Add the usage to the local usage table. */ + hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usages[hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage] = usage; + + /* We have one more usage now. */ + hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage++; + + break; + + + case UX_HOST_CLASS_HID_LOCAL_TAG_USAGE_MINIMUM: + + /* Usage Minimum tag. */ + hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_min = + (ULONG) _ux_host_class_hid_item_data_get(descriptor, item); + + break; + + + case UX_HOST_CLASS_HID_LOCAL_TAG_USAGE_MAXIMUM: + + /* Usage Maximum tag. */ + hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_max = + (ULONG) _ux_host_class_hid_item_data_get(descriptor, item); + + /* Check if the maximum value is coherent with the minimum. */ + if (hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_max < hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_min) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_MIN_MAX_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_MIN_MAX_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_MIN_MAX_ERROR); + } + + /* Get the boundaries for the usage values which are defined when encountering the USAGE MAX tag. */ + usage_min = (ULONG)(hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_min); + usage_max = (ULONG)(hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_max); + + while (usage_min <= usage_max) + { + + /* Check if we can still add this usage. */ + if (hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage == UX_HOST_CLASS_HID_USAGES) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_USAGE_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_USAGE_OVERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_USAGE_OVERFLOW); + + } + + /* Combine the global usage with the local usage to form a unique usage ID. */ + usage = usage_min | (hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_usage_page << 16); + + /* Add the usage to the local usage table. */ + hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usages[hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage] = usage; + + /* We have one more usage now. */ + hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage++; + + /* Next usage value. */ + usage_min++; + } + + break; + + case UX_HOST_CLASS_HID_LOCAL_TAG_DELIMITER: + + /* Obtain the delimiter set from the descriptor. */ + delimiter_set = _ux_host_class_hid_item_data_get(descriptor, item); + + /* We should have either an open or a close. */ + switch (delimiter_set) + { + + case UX_HOST_CLASS_HID_DELIMITER_OPEN: + + /* Recursive delimiter opens are not supported. */ + if (hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_delimiter_level == 1) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_DELIMITER_ERROR); + + return(UX_HOST_CLASS_HID_DELIMITER_ERROR); + } + + /* Mark the opening of the delimiter. */ + hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_delimiter_level = 1; + + break; + + case UX_HOST_CLASS_HID_DELIMITER_CLOSE: + + /* Ensure we had an open delimiter before. */ + if (hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_delimiter_level == 0) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_DELIMITER_ERROR); + + return(UX_HOST_CLASS_HID_DELIMITER_ERROR); + } + + /* Mark the closing of the delimiter. */ + hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_delimiter_level = 0; + + break; + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_DELIMITER_ERROR); + + /* We got a wrong delimiter set. */ + return(UX_HOST_CLASS_HID_DELIMITER_ERROR); + } + break; + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_TAG_UNSUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_TAG_UNSUPPORTED, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* This tag is either unknown or unsupported. */ + return(UX_HOST_CLASS_HID_TAG_UNSUPPORTED); + } + + /* Return status. Always SUCCESS if we get here.*/ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_main_item_parse.c b/common/usbx_host_classes/src/ux_host_class_hid_main_item_parse.c new file mode 100644 index 0000000..352f900 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_main_item_parse.c @@ -0,0 +1,183 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_main_item_parse PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses a main item from the report descriptor. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* item Pointer to item */ +/* descriptor Pointer to descriptor */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_item_data_get Get data item */ +/* _ux_host_class_hid_report_add Add report */ +/* _ux_utility_memory_set Memory block set */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_main_item_parse(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_ITEM *item, UCHAR *descriptor) +{ + +UX_HOST_CLASS_HID_PARSER *hid_parser; +UINT status = UX_ERROR; +ULONG collection_type; + + + /* Get the temporary parser structure pointer. */ + hid_parser = &hid -> ux_host_class_hid_parser; + + /* Analyze the tag. */ + switch (item -> ux_host_class_hid_item_report_tag) + { + + case UX_HOST_CLASS_HID_MAIN_TAG_COLLECTION: + + /* We have a new collection to open. If the collection type is application, + we have to differentiate the first collection. */ + collection_type = _ux_host_class_hid_item_data_get(descriptor, item); + + /* Check the collection type. */ + if (collection_type == UX_HOST_CLASS_HID_COLLECTION_APPLICATION) + { + + /* We have a collection of type application, check if this is the first one */ + if ((hid_parser -> ux_host_class_hid_parser_main_page == 0) && (hid_parser -> ux_host_class_hid_parser_main_usage == 0)) + { + + /* It is the first application. Since the main usage and page have not yet + been defined, we use the global page and the current local usage. */ + hid_parser -> ux_host_class_hid_parser_main_page = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_usage_page; + hid_parser -> ux_host_class_hid_parser_main_usage = hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usages[0]; + } + + /* Memorize the application. */ + hid_parser -> ux_host_class_hid_parser_application = collection_type; + + /* Add one collection to this report */ + hid_parser -> ux_host_class_hid_parser_number_collection++; + + /* Set the status to success. */ + status = UX_SUCCESS; + } + else + { + + if (hid_parser -> ux_host_class_hid_parser_number_collection >= UX_HOST_CLASS_HID_MAX_COLLECTION) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_COLLECTION_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_COLLECTION_OVERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_COLLECTION_OVERFLOW); + } + else + { + + hid_parser -> ux_host_class_hid_parser_collection[hid_parser -> ux_host_class_hid_parser_number_collection] = collection_type; + + /* Add one collection to this report. */ + hid_parser -> ux_host_class_hid_parser_number_collection++; + + /* Set the status to success. */ + status = UX_SUCCESS; + } + } + break; + + case UX_HOST_CLASS_HID_MAIN_TAG_END_COLLECTION: + + /* We need to pop back the last collection. */ + if (hid_parser -> ux_host_class_hid_parser_number_collection == 0) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_COLLECTION_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_COLLECTION_OVERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_COLLECTION_OVERFLOW); + } + + else + + hid_parser -> ux_host_class_hid_parser_number_collection--; + + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_HID_MAIN_TAG_INPUT: + case UX_HOST_CLASS_HID_MAIN_TAG_OUTPUT: + case UX_HOST_CLASS_HID_MAIN_TAG_FEATURE: + + /* We need to add a report. */ + status = _ux_host_class_hid_report_add(hid, descriptor, item); + break; + } + + /* We have a new main item, so the local instances have to be cleaned. */ + _ux_utility_memory_set(&hid_parser -> ux_host_class_hid_parser_local, 0, sizeof(UX_HOST_CLASS_HID_LOCAL_ITEM)); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_mouse_activate.c b/common/usbx_host_classes/src/ux_host_class_hid_mouse_activate.c new file mode 100644 index 0000000..61cb418 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_mouse_activate.c @@ -0,0 +1,185 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Mouse Client Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_mouse.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_mouse_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs the enumeration of a HID mouse. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_idle_set Set idle rate */ +/* _ux_host_class_hid_report_callback_register */ +/* Register report callback */ +/* _ux_host_class_hid_report_id_get Get report ID */ +/* _ux_host_class_hid_periodic_report_start */ +/* Start periodic report */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HID Mouse Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_mouse_activate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) +{ + +UX_HOST_CLASS_HID_REPORT_CALLBACK call_back; +UX_HOST_CLASS_HID_REPORT_GET_ID report_id; +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT *hid_client; +UX_HOST_CLASS_HID_MOUSE *mouse_instance; +UINT status; + + + /* Get the instance to the HID class. */ + hid = command -> ux_host_class_hid_client_command_instance; + + /* And of the HID client. */ + hid_client = hid -> ux_host_class_hid_client; + + /* Get some memory for both the HID class instance of this client + and for the callback. */ + mouse_instance = (UX_HOST_CLASS_HID_MOUSE *) _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, + sizeof(UX_HOST_CLASS_HID_MOUSE)); + if(mouse_instance == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Attach the mouse instance to the client instance. */ + hid_client -> ux_host_class_hid_client_local_instance = (VOID *) mouse_instance; + + /* Save the HID instance in the client instance. */ + mouse_instance -> ux_host_class_hid_mouse_hid = hid; + + /* The instance is live now. */ + mouse_instance -> ux_host_class_hid_mouse_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* Get the report ID for the mouse. The mouse is a INPUT report. + This should be 0 but in case. */ + report_id.ux_host_class_hid_report_get_report = UX_NULL; + report_id.ux_host_class_hid_report_get_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT; + status = _ux_host_class_hid_report_id_get(hid, &report_id); + + /* The report ID should exist. */ + if (status == UX_SUCCESS) + { + + /* Save the mouse report ID. */ + mouse_instance -> ux_host_class_hid_mouse_id = (USHORT)report_id.ux_host_class_hid_report_get_id; + + /* Set the idle rate of the mouse to 0. This way a report is generated only when there is an activity. */ + status = _ux_host_class_hid_idle_set(hid, 0, mouse_instance -> ux_host_class_hid_mouse_id); + + /* Check for error, accept protocol error since it's optional for mouse. */ + if (status == UX_TRANSFER_STALLED) + status = UX_SUCCESS; + } + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + + /* Initialize the report callback. */ + call_back.ux_host_class_hid_report_callback_id = mouse_instance -> ux_host_class_hid_mouse_id; + call_back.ux_host_class_hid_report_callback_function = _ux_host_class_hid_mouse_callback; + call_back.ux_host_class_hid_report_callback_buffer = UX_NULL; + call_back.ux_host_class_hid_report_callback_flags = UX_HOST_CLASS_HID_REPORT_INDIVIDUAL_USAGE; + call_back.ux_host_class_hid_report_callback_length = 0; + + /* Register the report call back when data comes it on this report. */ + status = _ux_host_class_hid_report_callback_register(hid, &call_back); + } + + /* If we are OK, go on. */ + if (status == UX_SUCCESS) + { + + /* Start the periodic report. */ + status = _ux_host_class_hid_periodic_report_start(hid); + + if (status == UX_SUCCESS) + { + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_HID_CLIENT_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid_client); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_MOUSE_ACTIVATE, hid, mouse_instance, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Return completion status. */ + return(status); + } + } + + /* We are here if there is error. */ + + /* Detach the client instance. */ + hid_client -> ux_host_class_hid_client_local_instance = UX_NULL; + + /* Free mouse client instance. */ + _ux_utility_memory_free(mouse_instance); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_mouse_buttons_get.c b/common/usbx_host_classes/src/ux_host_class_hid_mouse_buttons_get.c new file mode 100644 index 0000000..139c9f0 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_mouse_buttons_get.c @@ -0,0 +1,100 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Mouse Client Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_mouse.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_mouse_buttons_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads the mouse buttons and reports it to the user. */ +/* */ +/* INPUT */ +/* */ +/* mouse_instance Pointer to mouse instance */ +/* mouse_buttons Current Mouse Buttons */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance */ +/* */ +/* CALLED BY */ +/* */ +/* HID Mouse Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_mouse_buttons_get(UX_HOST_CLASS_HID_MOUSE *mouse_instance, + ULONG *mouse_buttons) +{ + +UX_HOST_CLASS_HID *hid; + + /* Get the HID class associated with the HID client. */ + hid = mouse_instance -> ux_host_class_hid_mouse_hid; + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Report the mouse buttons. */ + *mouse_buttons = mouse_instance -> ux_host_class_hid_mouse_buttons; + + /* The status will tell the application there is something valid in the usage/value. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_mouse_callback.c b/common/usbx_host_classes/src/ux_host_class_hid_mouse_callback.c new file mode 100644 index 0000000..9e453e1 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_mouse_callback.c @@ -0,0 +1,149 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Mouse Client Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_mouse.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_mouse_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the callback mechanism for a report registration. */ +/* For the mouse, we filter the mouse coordinate changes and the */ +/* state of the buttons. */ +/* */ +/* INPUT */ +/* */ +/* callback Pointer to callback */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hid_mouse_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK *callback) +{ + +UX_HOST_CLASS_HID_CLIENT *hid_client; +UX_HOST_CLASS_HID_MOUSE *mouse_instance; + + /* Get the HID client instance that issued the callback. */ + hid_client = callback -> ux_host_class_hid_report_callback_client; + + /* Get the mouse local instance */ + mouse_instance = (UX_HOST_CLASS_HID_MOUSE *) hid_client -> ux_host_class_hid_client_local_instance; + + /* Analyze the usage we have received. */ + switch (callback -> ux_host_class_hid_report_callback_usage) + { + + + /* X/Y Axis movement. */ + case UX_HOST_CLASS_HID_MOUSE_AXIS_X : + + /* Add the deplacement to the position. */ + mouse_instance -> ux_host_class_hid_mouse_x_position += (SCHAR) callback -> ux_host_class_hid_report_callback_value; + + break; + + case UX_HOST_CLASS_HID_MOUSE_AXIS_Y : + + /* Add the deplacement to the position. */ + mouse_instance -> ux_host_class_hid_mouse_y_position += (SCHAR) callback -> ux_host_class_hid_report_callback_value; + break; + + /* Buttons. */ + case UX_HOST_CLASS_HID_MOUSE_BUTTON_1 : + + /* Check the state of button 1. */ + if (callback -> ux_host_class_hid_report_callback_value == UX_TRUE) + mouse_instance -> ux_host_class_hid_mouse_buttons |= UX_HOST_CLASS_HID_MOUSE_BUTTON_1_PRESSED; + else + mouse_instance -> ux_host_class_hid_mouse_buttons &= (ULONG)~UX_HOST_CLASS_HID_MOUSE_BUTTON_1_PRESSED; + break; + + case UX_HOST_CLASS_HID_MOUSE_BUTTON_2 : + + /* Check the state of button 2. */ + if (callback -> ux_host_class_hid_report_callback_value == UX_TRUE) + mouse_instance -> ux_host_class_hid_mouse_buttons |= UX_HOST_CLASS_HID_MOUSE_BUTTON_2_PRESSED; + else + mouse_instance -> ux_host_class_hid_mouse_buttons &= (ULONG)~UX_HOST_CLASS_HID_MOUSE_BUTTON_2_PRESSED; + break; + + case UX_HOST_CLASS_HID_MOUSE_BUTTON_3 : + + /* Check the state of button 3. */ + if (callback -> ux_host_class_hid_report_callback_value == UX_TRUE) + mouse_instance -> ux_host_class_hid_mouse_buttons |= UX_HOST_CLASS_HID_MOUSE_BUTTON_3_PRESSED; + else + mouse_instance -> ux_host_class_hid_mouse_buttons &= (ULONG)~UX_HOST_CLASS_HID_MOUSE_BUTTON_3_PRESSED; + break; + + + /* Wheel movement. */ + case UX_HOST_CLASS_HID_MOUSE_WHEEL : + + mouse_instance -> ux_host_class_hid_mouse_wheel += (SCHAR) callback -> ux_host_class_hid_report_callback_value; + + break; + + default : + + /* We have received a Usage we don't know about. Ignore it. */ + break; + } + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_mouse_deactivate.c b/common/usbx_host_classes/src/ux_host_class_hid_mouse_deactivate.c new file mode 100644 index 0000000..8a06cf4 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_mouse_deactivate.c @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Mouse Client Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_mouse.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_mouse_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs the deactivation of a HID mouse. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_periodic_report_stop */ +/* Stop periodic report */ +/* _ux_utility_memory_free Free memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HID Mouse Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_mouse_deactivate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) +{ + +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT *hid_client; +UINT status; + + + /* Get the instance to the HID class. */ + hid = command -> ux_host_class_hid_client_command_instance; + + /* Stop the periodic report. */ + status = _ux_host_class_hid_periodic_report_stop(hid); + + /* Get the HID client pointer. */ + hid_client = hid -> ux_host_class_hid_client; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_MOUSE_DEACTIVATE, hid, hid_client -> ux_host_class_hid_client_local_instance, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Now free the instance memory. */ + _ux_utility_memory_free(hid_client -> ux_host_class_hid_client_local_instance); + + /* We may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_HID_CLIENT_REMOVAL, hid -> ux_host_class_hid_class, (VOID *) hid_client); + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_mouse_entry.c b/common/usbx_host_classes/src/ux_host_class_hid_mouse_entry.c new file mode 100644 index 0000000..a81662d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_mouse_entry.c @@ -0,0 +1,119 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Mouse Client Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_mouse.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_mouse_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the HID Mouse client. This */ +/* function is called by the HID class after it has parsed a new HID */ +/* report descriptor and is searching for a HID client. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_mouse_activate Activate HID mouse class */ +/* _ux_host_class_hid_mouse_deactivate Deactivate HID mouse class */ +/* */ +/* CALLED BY */ +/* */ +/* Host Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_mouse_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_hid_client_command_request) + { + + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the HID class know if we want to own + this device or not. */ + if ((command -> ux_host_class_hid_client_command_page == UX_HOST_CLASS_HID_PAGE_GENERIC_DESKTOP_CONTROLS) && + (command -> ux_host_class_hid_client_command_usage == UX_HOST_CLASS_HID_GENERIC_DESKTOP_MOUSE)) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used by the HID class to start the HID client. */ + status = _ux_host_class_hid_mouse_activate(command); + + /* Return completion status. */ + return(status); + + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used by the HID class when it received a deactivate + command from the USBX stack and there was a HID client attached to the HID instance. */ + status = _ux_host_class_hid_mouse_deactivate(command); + + /* Return completion status. */ + return(status); + } + + /* Return error status. */ + return(UX_ERROR); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_mouse_position_get.c b/common/usbx_host_classes/src/ux_host_class_hid_mouse_position_get.c new file mode 100644 index 0000000..3b582f7 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_mouse_position_get.c @@ -0,0 +1,106 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Mouse Client Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_mouse.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_mouse_position_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads the mouse position and reports it to the user. */ +/* We have the X and Y coordinates passed by the application. */ +/* */ +/* INPUT */ +/* */ +/* mouse_instance Pointer to mouse instance */ +/* mouse_x_position Current Mouse X Position */ +/* mouse_y_position Current Mouse Y Position */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* HID Mouse Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_mouse_position_get(UX_HOST_CLASS_HID_MOUSE *mouse_instance, + SLONG *mouse_x_position, + SLONG *mouse_y_position) +{ + +UX_HOST_CLASS_HID *hid; + + /* Get the HID class associated with the HID client. */ + hid = mouse_instance -> ux_host_class_hid_mouse_hid; + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Report the mouse X position. */ + *mouse_x_position = mouse_instance -> ux_host_class_hid_mouse_x_position; + + /* Report the mouse Y position. */ + *mouse_y_position = mouse_instance -> ux_host_class_hid_mouse_y_position; + + /* The status will tell the application there is something valid in the usage/value. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_mouse_wheel_get.c b/common/usbx_host_classes/src/ux_host_class_hid_mouse_wheel_get.c new file mode 100644 index 0000000..7b20092 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_mouse_wheel_get.c @@ -0,0 +1,100 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Mouse Client Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_mouse.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_mouse_wheel_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads the mouse wheel position (up or down). */ +/* */ +/* INPUT */ +/* */ +/* mouse_instance Pointer to mouse instance */ +/* mouse_wheel_movement Current Mouse wheel movement */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* HID Mouse Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_mouse_wheel_get(UX_HOST_CLASS_HID_MOUSE *mouse_instance, + SLONG *mouse_wheel_movement) +{ + +UX_HOST_CLASS_HID *hid; + + /* Get the HID class associated with the HID client. */ + hid = mouse_instance -> ux_host_class_hid_mouse_hid; + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Report the mouse wheel movement. */ + *mouse_wheel_movement = (SLONG)(mouse_instance -> ux_host_class_hid_mouse_wheel); + + /* The status will tell the application there is something valid in the usage/value. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_start.c b/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_start.c new file mode 100644 index 0000000..eb11b5d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_start.c @@ -0,0 +1,135 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_periodic_report_start PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts the interrupt endpoint to obtain the periodic */ +/* report. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_periodic_report_start(UX_HOST_CLASS_HID *hid) +{ + +UINT status; +UX_TRANSFER *transfer_request; + + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* Check the status of the interrupt endpoint. */ + if (hid -> ux_host_class_hid_interrupt_endpoint_status != UX_HOST_CLASS_HID_INTERRUPT_ENDPOINT_READY) + { + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_PERIODIC_REPORT_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_PERIODIC_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error status. */ + return(UX_HOST_CLASS_HID_PERIODIC_REPORT_ERROR); + } + + /* Get the address of the HID associated with the interrupt endpoint. */ + transfer_request = &hid -> ux_host_class_hid_interrupt_endpoint -> ux_endpoint_transfer_request; + + /* The transfer on the interrupt endpoint can be started. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check the status. If no error, adjust the status of the periodic endpoint + to active. */ + if (status == UX_SUCCESS) + hid -> ux_host_class_hid_interrupt_endpoint_status = UX_HOST_CLASS_HID_INTERRUPT_ENDPOINT_ACTIVE; + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Return the function status */ + return(status); +} diff --git a/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_stop.c b/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_stop.c new file mode 100644 index 0000000..5b5845c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_periodic_report_stop.c @@ -0,0 +1,113 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_periodic_report_stop PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function stops the interrupt endpoint of the HID class */ +/* instance. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_endpoint_transfer_abort Abort transfer on endpoint */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_periodic_report_stop(UX_HOST_CLASS_HID *hid) +{ + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Check the status of the interrupt endpoint. */ + if (hid -> ux_host_class_hid_interrupt_endpoint_status != UX_HOST_CLASS_HID_INTERRUPT_ENDPOINT_ACTIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_PERIODIC_REPORT_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_PERIODIC_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_PERIODIC_REPORT_ERROR); + } + + /* Abort the transfer going on on the endpoint now. */ + _ux_host_stack_endpoint_transfer_abort(hid -> ux_host_class_hid_interrupt_endpoint); + + /* Regardless of the status, we update the status of the endpoint. */ + hid -> ux_host_class_hid_interrupt_endpoint_status = UX_HOST_CLASS_HID_INTERRUPT_ENDPOINT_READY; + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_remote_control_activate.c b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_activate.c new file mode 100644 index 0000000..0cb1032 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_activate.c @@ -0,0 +1,180 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Remote Control Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_remote_control.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_remote_control_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs the enumeration of a HID Remote Control */ +/* class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_periodic_report_start Start periodic report */ +/* _ux_host_class_hid_report_callback_register Register callback */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HID Remote Control Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_remote_control_activate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) +{ + +UX_HOST_CLASS_HID_REPORT_CALLBACK call_back; +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT *hid_client; +UX_HOST_CLASS_HID_REMOTE_CONTROL *remote_control_instance; +UINT status = UX_SUCCESS; + + + /* Get the instance to the HID class. */ + hid = command -> ux_host_class_hid_client_command_instance; + + /* And of the HID client. */ + hid_client = hid -> ux_host_class_hid_client; + + /* Get some memory for both the HID class instance of this client + and for the callback. */ + remote_control_instance = (UX_HOST_CLASS_HID_REMOTE_CONTROL *) _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, + sizeof(UX_HOST_CLASS_HID_REMOTE_CONTROL)); + if (remote_control_instance == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Attach the remote control instance to the client instance. */ + hid_client -> ux_host_class_hid_client_local_instance = (VOID *) remote_control_instance; + + /* Save the HID instance in the client instance. */ + remote_control_instance -> ux_host_class_hid_remote_control_hid = hid; + + /* The instance is live now. */ + remote_control_instance -> ux_host_class_hid_remote_control_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* Allocate the round-robin buffer that the remote control instance will use + * to store the usages as they come in. + * Size calculation overflow is checked near where _USAGE_ARRAY_LENGTH is defined. + */ + remote_control_instance -> ux_host_class_hid_remote_control_usage_array = (ULONG *) + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, + UX_HOST_CLASS_HID_REMOTE_CONTROL_USAGE_ARRAY_LENGTH*4); + + /* Check memory pointer. */ + if (remote_control_instance -> ux_host_class_hid_remote_control_usage_array == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + + /* If there is no error, go on. */ + if (status == UX_SUCCESS) + { + + /* Initialize the head and tail of this array. */ + remote_control_instance -> ux_host_class_hid_remote_control_usage_array_head = remote_control_instance -> ux_host_class_hid_remote_control_usage_array; + remote_control_instance -> ux_host_class_hid_remote_control_usage_array_tail = remote_control_instance -> ux_host_class_hid_remote_control_usage_array; + + /* Initialize the report callback. */ + call_back.ux_host_class_hid_report_callback_id = 0; + call_back.ux_host_class_hid_report_callback_function = _ux_host_class_hid_remote_control_callback; + call_back.ux_host_class_hid_report_callback_buffer = UX_NULL; + call_back.ux_host_class_hid_report_callback_flags = UX_HOST_CLASS_HID_REPORT_INDIVIDUAL_USAGE; + call_back.ux_host_class_hid_report_callback_length = 0; + + /* Register the report call back when data comes in on this report. */ + status = _ux_host_class_hid_report_callback_register(hid, &call_back); + } + + /* If there is no error, go on. */ + if (status == UX_SUCCESS) + { + + /* Start the periodic report. */ + status = _ux_host_class_hid_periodic_report_start(hid); + + /* If OK, we are done. */ + if (status == UX_SUCCESS) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_REMOTE_CONTROL_ACTIVATE, hid, remote_control_instance, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_HID_CLIENT_INSERTION, hid -> ux_host_class_hid_class, (VOID *) hid_client); + } + + /* We are done success. */ + return (UX_SUCCESS); + } + } + + /* We are here when there is error. */ + + /* Detach instance. */ + hid_client -> ux_host_class_hid_client_local_instance = UX_NULL; + + /* Free usage array. */ + if (remote_control_instance -> ux_host_class_hid_remote_control_usage_array) + _ux_utility_memory_free(remote_control_instance -> ux_host_class_hid_remote_control_usage_array); + + /* Free instance memory. */ + _ux_utility_memory_free(remote_control_instance); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_remote_control_callback.c b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_callback.c new file mode 100644 index 0000000..0997f2d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_callback.c @@ -0,0 +1,131 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Remote Control Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_remote_control.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_remote_control_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the callback mechanism for a report registration. */ +/* */ +/* INPUT */ +/* */ +/* callback Pointer to callback */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* HID Remote Control Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hid_remote_control_callback(UX_HOST_CLASS_HID_REPORT_CALLBACK *callback) +{ + +UX_HOST_CLASS_HID_CLIENT *hid_client; +UX_HOST_CLASS_HID_REMOTE_CONTROL *remote_control_instance; +ULONG *array_head; +ULONG *array_tail; +ULONG *array_end; +ULONG *array_start; +ULONG *array_head_next; + + + /* Get the HID client instance that issued the callback. */ + hid_client = callback -> ux_host_class_hid_report_callback_client; + + /* Get the remote control local instance. */ + remote_control_instance = (UX_HOST_CLASS_HID_REMOTE_CONTROL *) hid_client -> ux_host_class_hid_client_local_instance; + + /* Load the remote control usage/value array info. */ + array_start = remote_control_instance -> ux_host_class_hid_remote_control_usage_array; + array_end = array_start + UX_HOST_CLASS_HID_REMOTE_CONTROL_USAGE_ARRAY_LENGTH; + array_head = remote_control_instance -> ux_host_class_hid_remote_control_usage_array_head; + array_tail = remote_control_instance -> ux_host_class_hid_remote_control_usage_array_tail; + + /* We have a single usage/value. We have to store it into the array. If the array overflows, + there is no mechanism for flow control here so we ignore the usage/value until the + applications makes more room in the array. */ + + /* Get position where next head will be. */ + array_head_next = array_head + 2; + + /* The head always points to where we will insert the next element. This + is the reason for the wrap. */ + if (array_head_next == array_end) + array_head_next = array_start; + + /* Do we have enough space to store the new usage? */ + if (array_head_next != array_tail) + { + + /* Yes, we have some space. */ + *array_head = callback -> ux_host_class_hid_report_callback_usage; + *(array_head + 1) = callback -> ux_host_class_hid_report_callback_value; + + /* Now update the array head. */ + remote_control_instance -> ux_host_class_hid_remote_control_usage_array_head = array_head_next; + } + else + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_REMOTE_CONTROL_CALLBACK, hid_client, remote_control_instance, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Notify application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + } + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_remote_control_deactivate.c b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_deactivate.c new file mode 100644 index 0000000..8146336 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_deactivate.c @@ -0,0 +1,115 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Remote Control Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_remote_control.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_remote_control_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs the deactivation of a HID Remote Control */ +/* class instance. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_periodic_report_stop Stop periodic report */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HID Remote Control Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_remote_control_deactivate(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) +{ + +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT *hid_client; +UX_HOST_CLASS_HID_REMOTE_CONTROL *remote_control_instance; +UINT status; + + + /* Get the instance to the HID class. */ + hid = command -> ux_host_class_hid_client_command_instance; + + /* Stop the periodic report. */ + status = _ux_host_class_hid_periodic_report_stop(hid); + + /* Get the HID client pointer. */ + hid_client = hid -> ux_host_class_hid_client; + + /* Get the remote control local instance. */ + remote_control_instance = (UX_HOST_CLASS_HID_REMOTE_CONTROL *) hid_client -> ux_host_class_hid_client_local_instance; + + /* Unload all the memory used by the remote control client. */ + _ux_utility_memory_free(remote_control_instance -> ux_host_class_hid_remote_control_usage_array); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_REMOTE_CONTROL_DEACTIVATE, hid, remote_control_instance, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Now free the instance memory. */ + _ux_utility_memory_free(hid_client -> ux_host_class_hid_client_local_instance); + + /* We may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_HID_CLIENT_REMOVAL, hid -> ux_host_class_hid_class, (VOID *) hid_client); + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_remote_control_entry.c b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_entry.c new file mode 100644 index 0000000..6fb8812 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_entry.c @@ -0,0 +1,121 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Remote Control Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_remote_control.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_remote_control_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the HID Remote Control client. */ +/* This function is called by the HID class after it has parsed a new */ +/* HID report descriptor and is searching for a HID client. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_remote_control_activate */ +/* Activate HID RC class */ +/* _ux_host_class_hid_remote_control_deactivate */ +/* Deactivate HID RC class */ +/* */ +/* CALLED BY */ +/* */ +/* Host Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_remote_control_entry(UX_HOST_CLASS_HID_CLIENT_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_hid_client_command_request) + { + + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the HID class know if we want to own + this device or not */ + if ((command -> ux_host_class_hid_client_command_page == UX_HOST_CLASS_HID_PAGE_CONSUMER) && + (command -> ux_host_class_hid_client_command_usage == UX_HOST_CLASS_HID_CONSUMER_REMOTE_CONTROL)) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used by the HID class to start the HID client. */ + status = _ux_host_class_hid_remote_control_activate(command); + + /* Return completion status. */ + return(status); + + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used by the HID class when it received a deactivate + command from the USBX stack and there was a HID client attached to the HID instance */ + status = _ux_host_class_hid_remote_control_deactivate(command); + + /* Return completion status. */ + return(status); + } + + /* Return error status. */ + return(UX_ERROR); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_remote_control_usage_get.c b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_usage_get.c new file mode 100644 index 0000000..8fbd9a1 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_remote_control_usage_get.c @@ -0,0 +1,125 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Remote Control Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_class_hid_remote_control.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_remote_control_usage_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads the usage and value from the remote control */ +/* round-robin buffer. */ +/* */ +/* INPUT */ +/* */ +/* remote_control_instance Pointer to remote control */ +/* usage Pointer to usage */ +/* value Pointer to value */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* HID Remote Control Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_remote_control_usage_get(UX_HOST_CLASS_HID_REMOTE_CONTROL *remote_control_instance, ULONG *usage, ULONG *value) +{ + +ULONG *array_head; +ULONG *array_tail; +ULONG *array_end; +ULONG *array_start; +UX_HOST_CLASS_HID *hid; + + /* Get the HID class associated with the HID client. */ + hid = remote_control_instance -> ux_host_class_hid_remote_control_hid; + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Load the remote control usage/value array info. */ + array_start = remote_control_instance -> ux_host_class_hid_remote_control_usage_array; + array_end = array_start + UX_HOST_CLASS_HID_REMOTE_CONTROL_USAGE_ARRAY_LENGTH; + array_head = remote_control_instance -> ux_host_class_hid_remote_control_usage_array_head; + array_tail = remote_control_instance -> ux_host_class_hid_remote_control_usage_array_tail; + + /* We want to extract a usage/value from the circular queue of the remote control instance. */ + if (array_tail == array_head) + return(UX_ERROR); + + /* Get the usage/value from the current tail. */ + *usage = *array_tail; + *value = *(array_tail + 1); + + /* Now we need to update the tail value. Are we at the end of the array? */ + if ((array_tail+2) >= array_end) + array_tail = array_start; + else + array_tail += 2; + + /* Set the tail pointer. */ + remote_control_instance -> ux_host_class_hid_remote_control_usage_array_tail = array_tail; + + /* The status will tell the application there is something valid in the usage/value. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_add.c b/common/usbx_host_classes/src/ux_host_class_hid_report_add.c new file mode 100644 index 0000000..59ca089 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_add.c @@ -0,0 +1,291 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_report_add PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds a report (input/output/feature) to the current */ +/* parser. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* descriptor Pointer to descriptor */ +/* item Pointer to item */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_item_data_get Get data item */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_copy Copy memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_report_add(UX_HOST_CLASS_HID *hid, UCHAR *descriptor, UX_HOST_CLASS_HID_ITEM *item) +{ + +UX_HOST_CLASS_HID_PARSER *hid_parser; +ULONG hid_field_value; +ULONG hid_field_count; +UX_HOST_CLASS_HID_REPORT *new_hid_report; +UX_HOST_CLASS_HID_REPORT *hid_report; +UX_HOST_CLASS_HID_FIELD *hid_field; +UX_HOST_CLASS_HID_FIELD *new_hid_field; +ULONG current_field_address; + + + /* Get the parser structure pointer. */ + hid_parser = &hid -> ux_host_class_hid_parser; + + /* Obtain the field value from the report. */ + hid_field_value = _ux_host_class_hid_item_data_get(descriptor, item); + + /* Allocate some memory to store this new report. */ + new_hid_report = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS_HID_REPORT)); + if (new_hid_report == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* We need to select the report entry based on the type of report. If the entry in the + report chain is NULL, this is the first report so update the start of the chain. */ + switch (item -> ux_host_class_hid_item_report_tag) + { + + case UX_HOST_CLASS_HID_MAIN_TAG_INPUT: + + hid_report = hid_parser -> ux_host_class_hid_parser_input_report; + if (hid_report == UX_NULL) + hid_parser -> ux_host_class_hid_parser_input_report = new_hid_report; + + /* This is a Input report. */ + new_hid_report -> ux_host_class_hid_report_type = UX_HOST_CLASS_HID_REPORT_TYPE_INPUT; + break; + + case UX_HOST_CLASS_HID_MAIN_TAG_OUTPUT: + + hid_report = hid_parser -> ux_host_class_hid_parser_output_report; + if (hid_report == UX_NULL) + hid_parser -> ux_host_class_hid_parser_output_report = new_hid_report; + + /* This is output report. */ + new_hid_report -> ux_host_class_hid_report_type = UX_HOST_CLASS_HID_REPORT_TYPE_OUTPUT; + break; + + case UX_HOST_CLASS_HID_MAIN_TAG_FEATURE: + + hid_report = hid_parser -> ux_host_class_hid_parser_feature_report; + if (hid_report == UX_NULL) + hid_parser -> ux_host_class_hid_parser_feature_report = new_hid_report; + + /* This is a Feature report. */ + new_hid_report -> ux_host_class_hid_report_type = UX_HOST_CLASS_HID_REPORT_TYPE_FEATURE; + break; + + + default: + + _ux_utility_memory_free(new_hid_report); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_HOST_CLASS_HID_REPORT_ERROR); + } + + /* If there is a preceding report, locate the end of the report chain. */ + if (hid_report != UX_NULL) + { + + while (hid_report -> ux_host_class_hid_report_next_report != UX_NULL) + hid_report = hid_report -> ux_host_class_hid_report_next_report; + } + + /* If this report is part of the current global report, use the last report + to add the fields. */ + if ((hid_report != UX_NULL) && (hid_report -> ux_host_class_hid_report_id == hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_id)) + { + + /* So we did not need a new report afterall! */ + _ux_utility_memory_free(new_hid_report); + new_hid_report = hid_report; + } + else + { + + /* We do have to build a new report. Add the new one to the chain. */ + if (hid_report != UX_NULL) + hid_report -> ux_host_class_hid_report_next_report = new_hid_report; + + /* Add the new report ID. */ + new_hid_report -> ux_host_class_hid_report_id = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_id; + } + + /* Compute the size of the report. The size is first calculated in bits. */ + current_field_address = new_hid_report -> ux_host_class_hid_report_bit_length; + new_hid_report -> ux_host_class_hid_report_bit_length += hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_size* + hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_count; + + /* Now compute the size in bytes (easier for the end/receive reports functions). */ + new_hid_report -> ux_host_class_hid_report_byte_length = new_hid_report -> ux_host_class_hid_report_bit_length >> 3; + + /* Take care of the bit padding if necessary. */ + if (new_hid_report -> ux_host_class_hid_report_bit_length & 7) + new_hid_report -> ux_host_class_hid_report_byte_length++; + + /* Get the number of field usage for this report, this value depends on the report type. If this is + an array, we use the number of usages; if this a variable, we use the report count. */ + if (hid_field_value & UX_HOST_CLASS_HID_ITEM_VARIABLE) + hid_field_count = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_count; + else + hid_field_count = hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_number_usage; + + /* If the field count is null, this is only padding and there is no field to be allocated to the report. */ + if (hid_field_count == 0) + return(UX_SUCCESS); + + /* Create the field structure. */ + new_hid_field = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS_HID_FIELD)); + if (new_hid_field == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Attach the new field to the report. The report may already contain a field, if so parse the chain + until we reach the end of the chain. */ + new_hid_report -> ux_host_class_hid_report_number_item += hid_field_count; + if (new_hid_report -> ux_host_class_hid_report_field == UX_NULL) + { + + /* This is the first field for the report. */ + new_hid_report -> ux_host_class_hid_report_field = new_hid_field; + } + else + { + + /* We have previous HID fields, so search for the end of the chain. */ + hid_field = new_hid_report -> ux_host_class_hid_report_field; + while(hid_field -> ux_host_class_hid_field_next_field != UX_NULL) + hid_field = hid_field -> ux_host_class_hid_field_next_field; + + /* Attach the new field to the end of the chain. */ + hid_field -> ux_host_class_hid_field_next_field = new_hid_field; + } + + /* From the parser structure, update the new field values. Start with logical values. */ + new_hid_field -> ux_host_class_hid_field_logical_min = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_logical_min; + new_hid_field -> ux_host_class_hid_field_logical_max = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_logical_max; + + /* Then the usage values. Note that these are only used if the item is an array. */ + new_hid_field -> ux_host_class_hid_field_usage_page = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_usage_page; + new_hid_field -> ux_host_class_hid_field_usage_min = hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_min; + new_hid_field -> ux_host_class_hid_field_usage_max = hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usage_max; + + /* Then physical values. */ + new_hid_field -> ux_host_class_hid_field_physical_min = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_physical_min; + new_hid_field -> ux_host_class_hid_field_physical_max = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_physical_max; + + /* Then unit values. */ + new_hid_field -> ux_host_class_hid_field_unit = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_unit; + new_hid_field -> ux_host_class_hid_field_unit_expo = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_unit_expo; + + /* Then report values. */ + new_hid_field -> ux_host_class_hid_field_report_type = item -> ux_host_class_hid_item_report_tag; + new_hid_field -> ux_host_class_hid_field_report_id = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_id; + new_hid_field -> ux_host_class_hid_field_report_size = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_size; + new_hid_field -> ux_host_class_hid_field_report_count = hid_parser -> ux_host_class_hid_parser_global.ux_host_class_hid_global_item_report_count; + new_hid_field -> ux_host_class_hid_field_report_offset = current_field_address; + + /* Save the HID field value. */ + new_hid_field -> ux_host_class_hid_field_value = hid_field_value; + + /* We need some memory for the values. */ + new_hid_field -> ux_host_class_hid_field_values = _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, + new_hid_field -> ux_host_class_hid_field_report_count, 4); + + /* Check the memory pointer. */ + if (new_hid_field -> ux_host_class_hid_field_values == UX_NULL) + { + + _ux_utility_memory_free(new_hid_field); + return(UX_MEMORY_INSUFFICIENT); + } + + /* We need some memory for the usages, but only for variable items; usage + values for array items can be calculated. */ + if (hid_field_value & UX_HOST_CLASS_HID_ITEM_VARIABLE) + { + + /* Allocate memory for the usages. */ + new_hid_field -> ux_host_class_hid_field_usages = _ux_utility_memory_allocate_mulc_safe(UX_NO_ALIGN, UX_REGULAR_MEMORY, hid_field_count, 4); + if (new_hid_field -> ux_host_class_hid_field_usages == UX_NULL) + { + + _ux_utility_memory_free(new_hid_field -> ux_host_class_hid_field_values); + _ux_utility_memory_free(new_hid_field); + return(UX_MEMORY_INSUFFICIENT); + } + + /* Copy the current usages in the field structure. */ + _ux_utility_memory_copy(new_hid_field -> ux_host_class_hid_field_usages, hid_parser -> ux_host_class_hid_parser_local.ux_host_class_hid_local_item_usages, hid_field_count*4); + } + + /* Save the number of usages. */ + new_hid_field -> ux_host_class_hid_field_number_usage = hid_field_count; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_callback_register.c b/common/usbx_host_classes/src/ux_host_class_hid_report_callback_register.c new file mode 100644 index 0000000..960d810 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_callback_register.c @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_report_callback_register PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will register a report callback to a HID report. */ +/* This function should be called by a HID client when it has been */ +/* instantiated by a new HID device. */ +/* */ +/* The registration process will allow the HID class to call a */ +/* function in the HID client when an asynchronous report is present. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* call_back HID report callback */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify class instance is valid*/ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_report_callback_register(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_REPORT_CALLBACK *call_back) +{ + +UINT status; +UX_HOST_CLASS_HID_REPORT *hid_report; + + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); + if (status!=UX_SUCCESS) + + /* Return error. */ + return(status); + + /* Search for the report ID. Note that this can only be an Input report! */ + hid_report = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_input_report; + + /* Parse all the report IDs in search of the one specified by the user. */ + while (hid_report != UX_NULL) + { + + /* Check report ID. */ + if (hid_report -> ux_host_class_hid_report_id == call_back -> ux_host_class_hid_report_callback_id) + { + + /* We have found the correct report. Set the call back function, buffer and flags. */ + hid_report -> ux_host_class_hid_report_callback_function = call_back -> ux_host_class_hid_report_callback_function; + hid_report -> ux_host_class_hid_report_callback_buffer = call_back -> ux_host_class_hid_report_callback_buffer; + hid_report -> ux_host_class_hid_report_callback_flags = call_back -> ux_host_class_hid_report_callback_flags; + hid_report -> ux_host_class_hid_report_callback_length = call_back -> ux_host_class_hid_report_callback_length; + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Tell the user the report was OK and the call back was registered. */ + return(UX_SUCCESS); + } + + /* Jump to next report. */ + hid_report = hid_report -> ux_host_class_hid_report_next_report; + } + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* The report ID could not be found amongst the reports. */ + return(UX_HOST_CLASS_HID_REPORT_ERROR); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_compress.c b/common/usbx_host_classes/src/ux_host_class_hid_report_compress.c new file mode 100644 index 0000000..2264881 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_compress.c @@ -0,0 +1,207 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_report_compress PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will compress a client report into a report buffer. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* client_report Pointer to client report */ +/* report_buffer Pointer to report buffer */ +/* report_length Length of report */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_report_compress(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report, + UCHAR *report_buffer, ULONG report_length) +{ + +UX_HOST_CLASS_HID_REPORT *hid_report; +UX_HOST_CLASS_HID_FIELD *hid_field; +ULONG field_usage; +ULONG field_report_count; +ULONG field_report_size; +ULONG *client_buffer; +ULONG client_value; +UCHAR value; +ULONG data_offset_bit; +UCHAR is_valid_usage; + + UX_PARAMETER_NOT_USED(hid); + UX_PARAMETER_NOT_USED(report_length); + + /* Get the report pointer from the caller. */ + hid_report = client_report -> ux_host_class_hid_client_report; + + /* Get the pointer to the user buffer. */ + client_buffer = client_report -> ux_host_class_hid_client_report_buffer; + + /* Get the first field associated with the report. */ + hid_field = hid_report -> ux_host_class_hid_report_field; + + /* Set data offset bit. */ + data_offset_bit = 0; + + /* We need to compress each field defined in the report. */ + while (hid_field != UX_NULL) + { + + /* Each report field has a report count value. This count is used to extract + values from the incoming report and build each usage/value instance. */ + for (field_report_count = 0; field_report_count < hid_field -> ux_host_class_hid_field_report_count; field_report_count++) + { + + /* Ensure the usage in the client buffer is valid. How we determine + this depends on whether the field is VARIABLE or ARRAY. */ + is_valid_usage = UX_FALSE; + if (hid_field -> ux_host_class_hid_field_value & UX_HOST_CLASS_HID_ITEM_VARIABLE) + { + + /* Go through the usage array to try and find the client's usage. */ + for (field_usage = 0; field_usage < hid_field -> ux_host_class_hid_field_number_usage; field_usage++) + { + + /* Is this a usage we've recorded? */ + if (*client_buffer == hid_field -> ux_host_class_hid_field_usages[field_usage]) + { + + /* Yes, this is a valid usage. */ + is_valid_usage = UX_TRUE; + break; + } + } + } + else + { + + /* Is the usage page valid? */ + if (((*client_buffer & 0xffff0000) >> 16) == hid_field -> ux_host_class_hid_field_usage_page) + { + + /* Is the usage in the min and max range? */ + if ((*client_buffer & 0xffff) >= hid_field -> ux_host_class_hid_field_usage_min && + (*client_buffer & 0xffff) <= hid_field -> ux_host_class_hid_field_usage_max) + { + + /* Yes, this is a valid usage. */ + is_valid_usage = UX_TRUE; + } + } + } + + /* Is the usage invalid? */ + if (is_valid_usage == UX_FALSE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_HID_REPORT_ERROR); + } + + /* Skip the usage and point the buffer to the value. */ + client_buffer++; + + /* Read the client value. */ + client_value = *client_buffer++; + + /* Build the value field in the report buffer bit by bit. */ + for (field_report_size = hid_field -> ux_host_class_hid_field_report_size; field_report_size > 0; field_report_size--) + { + + /* Isolate each bit from the report value. */ + value = (UCHAR) client_value & 1; + + /* Shift the isolated bit to its right space in the report byte. */ + value = (UCHAR)(value << data_offset_bit); + + /* Update the report with the bit value. */ + *report_buffer |= value; + + /* Move to next bit. */ + data_offset_bit++; + + /* Are we on a byte boundary. */ + if ((data_offset_bit & 7) == 0) + { + + /* If so increment the report address. */ + report_buffer++; + + /* Reset offset bit. */ + data_offset_bit = 0; + } + + /* Move to the next bit. */ + client_value = client_value >> 1; + } + } + + /* Move to the next field. */ + hid_field = hid_field -> ux_host_class_hid_field_next_field; + } + + /* Return successful completion. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_decompress.c b/common/usbx_host_classes/src/ux_host_class_hid_report_decompress.c new file mode 100644 index 0000000..e3eedcd --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_decompress.c @@ -0,0 +1,113 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_report_decompress PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will decompress a raw report into a client buffer. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* client_report Pointer to client report */ +/* report_buffer Pointer to report buffer */ +/* report_length Length of report */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_field_decompress Decompress field */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_report_decompress(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report, + UCHAR *report_buffer, ULONG report_length) +{ + +UX_HOST_CLASS_HID_REPORT *hid_report; +UX_HOST_CLASS_HID_FIELD *hid_field; + + UX_PARAMETER_NOT_USED(hid); + + /* Get the report pointer from the caller. */ + hid_report = client_report -> ux_host_class_hid_client_report; + + /* Check if this report has a ID field in the front. An ID field is required + if report ID is non null. */ + if (hid_report -> ux_host_class_hid_report_id != 0) + { + + /* We have an ID tag in the report. The ID tag is the first byte of the report. Skip the + ID tag and adjust the length. */ + report_buffer++; + report_length--; + } + + /* Get the first field associated with the report. */ + hid_field = hid_report -> ux_host_class_hid_report_field; + + /* We need to decompress each field defined in the report. */ + while (hid_field != UX_NULL) + { + + /* Decompress a field. */ + _ux_host_class_hid_field_decompress(hid_field, report_buffer, client_report); + + /* Move to the next field. */ + hid_field = hid_field -> ux_host_class_hid_field_next_field; + } + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_descriptor_get.c b/common/usbx_host_classes/src/ux_host_class_hid_report_descriptor_get.c new file mode 100644 index 0000000..628bebf --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_descriptor_get.c @@ -0,0 +1,204 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_report_descriptor_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the report descriptor and analyzes it. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* length Length of descriptor */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_global_item_parse Parse global item */ +/* _ux_host_class_hid_local_item_parse Parse local item */ +/* _ux_host_class_hid_report_item_analyse Analyze report */ +/* _ux_host_class_hid_resources_free Free HID resources */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_report_descriptor_get(UX_HOST_CLASS_HID *hid, ULONG length) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UCHAR *descriptor; +UCHAR *start_descriptor; +UX_HOST_CLASS_HID_ITEM item; +UINT status; + + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the report descriptor. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, length); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* We need to save the descriptor starting address. */ + start_descriptor = descriptor; + + /* Create a transfer_request for the GET_DESCRIPTOR request */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = length; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_HID_REPORT_DESCRIPTOR << 8; + transfer_request -> ux_transfer_request_index = hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == length)) + { + + /* Parse the report descriptor and build the report items. */ + while (length) + { + + /* Get one item from the report and analyze it. */ + _ux_host_class_hid_report_item_analyse(descriptor, &item); + + /* Point the descriptor right after the item identifier. */ + descriptor += item.ux_host_class_hid_item_report_format; + + /* Process relative to the item type. */ + switch (item.ux_host_class_hid_item_report_type) + { + + case UX_HOST_CLASS_HID_TYPE_GLOBAL: + + /* This is a global item. */ + status = _ux_host_class_hid_global_item_parse(hid, &item, descriptor); + break; + + + case UX_HOST_CLASS_HID_TYPE_MAIN: + + /* This is a main item. */ + status = _ux_host_class_hid_main_item_parse(hid, &item, descriptor); + break; + + + case UX_HOST_CLASS_HID_TYPE_LOCAL: + + /* This is a local item. */ + status = _ux_host_class_hid_local_item_parse(hid, &item, descriptor); + break; + + default: + + /* This is a reserved item, meaning it shouldn't be used! */ + + /* Set status to error. The check after this switch statement + will handle the rest. */ + status = UX_DESCRIPTOR_CORRUPTED; + break; + } + + /* Recheck the status code. */ + if (status != UX_SUCCESS) + { + break; + } + + /* Jump to the next item. */ + descriptor += item.ux_host_class_hid_item_report_length; + + /* Verify that the report descriptor is not corrupted. */ + if (length < item.ux_host_class_hid_item_report_length) + { + + /* Return error status. */ + status = (UX_DESCRIPTOR_CORRUPTED); + break; + } + + /* Adjust the length. */ + length -= (ULONG)(item.ux_host_class_hid_item_report_length + item.ux_host_class_hid_item_report_format); + } + } + else + + /* Descriptor length error! */ + status = UX_DESCRIPTOR_CORRUPTED; + + if (status != UX_SUCCESS) + { + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* The descriptor is corrupted! */ + _ux_host_class_hid_resources_free(hid); + } + + /* Free used resources. */ + _ux_utility_memory_free(start_descriptor); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_get.c b/common/usbx_host_classes/src/ux_host_class_hid_report_get.c new file mode 100644 index 0000000..add69ce --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_get.c @@ -0,0 +1,252 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_report_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets a report (input/output/feature) from the device. */ +/* The report can be either decompressed by the stack or raw. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* client_report Pointer to client report */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_report_decompress Decompress HID report */ +/* _ux_host_stack_class_instance_verify Verify the instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_copy Copy memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_report_get(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UCHAR *report_buffer; +UX_HOST_CLASS_HID_REPORT *hid_report; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_REPORT_GET, hid, client_report, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* Get the report pointer from the caller. */ + hid_report = client_report -> ux_host_class_hid_client_report; + + /* Ensure this is a INPUT report. */ + if (hid_report -> ux_host_class_hid_report_type != UX_HOST_CLASS_HID_REPORT_TYPE_INPUT) + { + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error. */ + return(UX_HOST_CLASS_HID_REPORT_ERROR); + } + + /* Check the report length, if 0, we don't need to do anything. */ + if (hid_report -> ux_host_class_hid_report_byte_length == 0) + { + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error code. */ + return(UX_HOST_CLASS_HID_REPORT_ERROR); + } + + /* Get some memory for reading the report. */ + report_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, hid_report -> ux_host_class_hid_report_byte_length); + if (report_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Return error code. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + { + + /* Something went wrong. */ + + /* Free all resources. */ + _ux_utility_memory_free(report_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + return(status); + } + + /* Create a transfer request for the GET_REPORT request. */ + transfer_request -> ux_transfer_request_data_pointer = report_buffer; + transfer_request -> ux_transfer_request_requested_length = hid_report -> ux_host_class_hid_report_byte_length; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_GET_REPORT; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = (UINT)((USHORT) hid_report -> ux_host_class_hid_report_id | (USHORT) hid_report -> ux_host_class_hid_report_type << 8); + transfer_request -> ux_transfer_request_index = hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == hid_report -> ux_host_class_hid_report_byte_length)) + { + + /* The report is now in memory in a raw format. The application may desire to keep it that way! */ + if (client_report -> ux_host_class_hid_client_report_flags & UX_HOST_CLASS_HID_REPORT_RAW) + { + + /* Ensure the user has given us enough memory for the raw buffer. */ + if (client_report -> ux_host_class_hid_client_report_length >= transfer_request -> ux_transfer_request_actual_length) + { + + /* We have enough memory to store the raw buffer. */ + _ux_utility_memory_copy(client_report -> ux_host_class_hid_client_report_buffer, report_buffer, transfer_request -> ux_transfer_request_actual_length); + + /* Set status to success. */ + status = UX_SUCCESS; + } + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_BUFFER_OVERFLOW, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Set overflow status. */ + status = UX_BUFFER_OVERFLOW; + } + } + else + { + + /* The report buffer must be parsed and decompressed. */ + status = _ux_host_class_hid_report_decompress(hid, client_report, report_buffer, transfer_request -> ux_transfer_request_actual_length); + } + } + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Set report error status. */ + status = UX_HOST_CLASS_HID_REPORT_ERROR; + } + + /* Free all resources. */ + _ux_utility_memory_free(report_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Return the completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_id_get.c b/common/usbx_host_classes/src/ux_host_class_hid_report_id_get.c new file mode 100644 index 0000000..71d1a26 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_id_get.c @@ -0,0 +1,178 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_report_id_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves the report after */ +/* report_id -> ux_host_class_hid_report_get_id and stores it in the */ +/* same pointer. If report_id -> ux_host_class_hid_report_get_id is */ +/* null, retrieves the first report of the type specified by */ +/* report_id -> ux_host_class_hid_report_get_type. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* report_id Report id structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* _ux_host_stack_class_instance_verify Verify class instance is valid*/ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_report_id_get(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_REPORT_GET_ID *report_id) +{ + +UINT status; +UX_HOST_CLASS_HID_REPORT *next_hid_report; + + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* Check if this is the first report to get. */ + if (report_id -> ux_host_class_hid_report_get_report == UX_NULL) + { + + /* Check for the type of report ID to get (Input, Output, Feature). */ + switch (report_id -> ux_host_class_hid_report_get_type) + { + + case UX_HOST_CLASS_HID_REPORT_TYPE_INPUT : + + /* Search for the input report ID. */ + next_hid_report = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_input_report; + break; + + case UX_HOST_CLASS_HID_REPORT_TYPE_OUTPUT : + + /* Search for the output report ID. */ + next_hid_report = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_output_report; + break; + + case UX_HOST_CLASS_HID_REPORT_TYPE_FEATURE : + + /* Search for the feature report ID. */ + next_hid_report = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_feature_report; + break; + + default : + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* The report ID could not be found amongst the reports. */ + next_hid_report = UX_NULL; + break; + } + } + else + { + + /* We had a report ID scan previously, point to the next report. */ + next_hid_report = report_id -> ux_host_class_hid_report_get_report -> ux_host_class_hid_report_next_report; + } + + /* Did we find the next report? */ + if (next_hid_report != UX_NULL) + { + + /* We want the first report, memorize the ID. */ + report_id -> ux_host_class_hid_report_get_id = next_hid_report -> ux_host_class_hid_report_id; + + /* And remember where we left. */ + report_id -> ux_host_class_hid_report_get_report = next_hid_report; + + /* Successfully found next report. */ + status = UX_SUCCESS; + } + else + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* No more reports. */ + status = UX_HOST_CLASS_HID_REPORT_ERROR; + } + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* The status variable has been set correctly. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_item_analyse.c b/common/usbx_host_classes/src/ux_host_class_hid_report_item_analyse.c new file mode 100644 index 0000000..d99351a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_item_analyse.c @@ -0,0 +1,128 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_report_item_analyse PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the report descriptor and analyzes it. */ +/* */ +/* INPUT */ +/* */ +/* descriptor Pointer to descriptor */ +/* item Pointer to item */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_report_item_analyse(UCHAR *descriptor, UX_HOST_CLASS_HID_ITEM *item) +{ + +UCHAR item_byte; + + + /* Get the first byte from the descriptor. */ + item_byte = *descriptor; + + /* We need to determine if this is a short or long item. + For long items, the tag is always 1111. */ + if ((item_byte & UX_HOST_CLASS_HID_ITEM_TAG_MASK) == UX_HOST_CLASS_HID_ITEM_TAG_LONG) + { + + /* We have a long item, mark its format. */ + item -> ux_host_class_hid_item_report_format = UX_HOST_CLASS_HID_ITEM_TAG_LONG; + + /* Set the type. */ + item -> ux_host_class_hid_item_report_type = (item_byte >> 2) & 3; + + /* Get its length (byte 1). */ + item -> ux_host_class_hid_item_report_length = (USHORT) *(descriptor + 1); + + /* Then the tag (byte 2). */ + item -> ux_host_class_hid_item_report_tag = *(descriptor + 2); + } + else + { + + /* We have a short item. Mark its format */ + item -> ux_host_class_hid_item_report_format = UX_HOST_CLASS_HID_ITEM_TAG_SHORT; + + /* Get the length of the item. */ + switch (item_byte & UX_HOST_CLASS_HID_ITEM_LENGTH_MASK) + { + + case 3: + + item -> ux_host_class_hid_item_report_length = 4; + break; + + default: + + item -> ux_host_class_hid_item_report_length = item_byte & UX_HOST_CLASS_HID_ITEM_LENGTH_MASK; + break; + } + + /* Set the type. */ + item -> ux_host_class_hid_item_report_type = (item_byte >> 2) & 3; + + /* Set the tag. */ + item -> ux_host_class_hid_item_report_tag = item_byte >> 4; + } + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_report_set.c b/common/usbx_host_classes/src/ux_host_class_hid_report_set.c new file mode 100644 index 0000000..688010a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_report_set.c @@ -0,0 +1,248 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_report_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets a report (input/output/feature) to the device. */ +/* The report can be either decompressed by the stack or raw. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* client_report Pointer to client report */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hid_report_compress Compress HID report */ +/* _ux_host_stack_class_instance_verify Verify the instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_copy Copy memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_report_set(UX_HOST_CLASS_HID *hid, UX_HOST_CLASS_HID_CLIENT_REPORT *client_report) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UCHAR *report_buffer; +UCHAR *current_report_buffer; +UX_HOST_CLASS_HID_REPORT *hid_report; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HID_REPORT_SET, hid, client_report, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_hid_name, (VOID *) hid) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* Get the report pointer from the caller. */ + hid_report = client_report -> ux_host_class_hid_client_report; + + /* Ensure this is NOT an INPUT report. */ + if (hid_report -> ux_host_class_hid_report_type == UX_HOST_CLASS_HID_REPORT_TYPE_INPUT) + { + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error code. */ + return(UX_HOST_CLASS_HID_REPORT_ERROR); + } + + /* Get some memory for sending the report. */ + if (hid_report -> ux_host_class_hid_report_id == 0) + report_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, hid_report -> ux_host_class_hid_report_byte_length); + else + report_buffer = _ux_utility_memory_allocate_add_safe(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, hid_report -> ux_host_class_hid_report_byte_length, 1); + + if (report_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Return error code. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Memorize the start of the real report buffer. */ + current_report_buffer = report_buffer; + + /* Check if there is a report ID to be inserted in front of the buffer. */ + if (hid_report -> ux_host_class_hid_report_id != 0) + *current_report_buffer++ = (UCHAR)(hid_report -> ux_host_class_hid_report_id); + + /* The report is in the client's buffer. It may be raw or or decompressed. If decompressed, + we need to create the report. */ + if (client_report -> ux_host_class_hid_client_report_flags & UX_HOST_CLASS_HID_REPORT_RAW) + { + + /* Ensure the user is not trying to overflow the report buffer. */ + if (hid_report -> ux_host_class_hid_report_byte_length >= client_report -> ux_host_class_hid_client_report_length) + { + + /* We have enough memory to store the raw buffer. */ + _ux_utility_memory_copy(current_report_buffer, client_report -> ux_host_class_hid_client_report_buffer, hid_report -> ux_host_class_hid_report_byte_length); + } + else + { + + /* Free allocated buffer. */ + _ux_utility_memory_free(report_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_OVERFLOW, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error code. */ + return(UX_HOST_CLASS_HID_REPORT_OVERFLOW); + } + } + else + { + + /* The report buffer has to be compressed. */ + _ux_host_class_hid_report_compress(hid, client_report, current_report_buffer, client_report -> ux_host_class_hid_client_report_length); + } + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hid -> ux_host_class_hid_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&hid -> ux_host_class_hid_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + { + + /* Something went wrong. */ + + /* Free all resources. */ + _ux_utility_memory_free(report_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + return(status); + } + + /* Create a transfer request for the SET_REPORT request. */ + transfer_request -> ux_transfer_request_data_pointer = report_buffer; + transfer_request -> ux_transfer_request_requested_length = hid_report -> ux_host_class_hid_report_byte_length; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HID_SET_REPORT; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = (UINT)((USHORT) hid_report -> ux_host_class_hid_report_id | (USHORT) hid_report -> ux_host_class_hid_report_type << 8); + transfer_request -> ux_transfer_request_index = hid -> ux_host_class_hid_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status != UX_SUCCESS) || (transfer_request -> ux_transfer_request_actual_length != hid_report -> ux_host_class_hid_report_byte_length)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_HID_REPORT_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_HID_REPORT_ERROR, hid, 0, 0, UX_TRACE_ERRORS, 0, 0) + + status = UX_HOST_CLASS_HID_REPORT_ERROR; + } + + /* Free all resources. */ + _ux_utility_memory_free(report_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&hid -> ux_host_class_hid_semaphore); + + /* Return the function status */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_resources_free.c b/common/usbx_host_classes/src/ux_host_class_hid_resources_free.c new file mode 100644 index 0000000..2cbacad --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_resources_free.c @@ -0,0 +1,78 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_resources_free PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function frees the resources allocated to a HID device. */ +/* */ +/* INPUT */ +/* */ +/* hid Pointer to HID class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hid_resources_free(UX_HOST_CLASS_HID *hid) +{ + + UX_PARAMETER_NOT_USED(hid); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hid_transfer_request_completed.c b/common/usbx_host_classes/src/ux_host_class_hid_transfer_request_completed.c new file mode 100644 index 0000000..6082c78 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hid_transfer_request_completed.c @@ -0,0 +1,269 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HID Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hid.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hid_transfer_request_completed PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the completion thread when a transfer */ +/* request has been completed either because the transfer is */ +/* successful or there was an error. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_hid_report_callback_function) */ +/* Callback function for report */ +/* _ux_host_class_hid_report_decompress Decompress HID report */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HID Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hid_transfer_request_completed(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_HID *hid; +UX_HOST_CLASS_HID_CLIENT *hid_client; +UX_HOST_CLASS_HID_REPORT *hid_report; +UINT status; +VOID *report_buffer; +UX_HOST_CLASS_HID_REPORT_CALLBACK callback; +UX_HOST_CLASS_HID_CLIENT_REPORT client_report; +ULONG *client_buffer; +UX_HOST_CLASS_HID_FIELD *hid_field; +ULONG field_report_count; + + /* Set Status to success. Optimistic view. */ + status = UX_SUCCESS; + + /* Get the class instance for this transfer request. */ + hid = (UX_HOST_CLASS_HID *) transfer_request -> ux_transfer_request_class_instance; + + /* Check the state of the transfer. If there is an error, we do not proceed with this report. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* We have an error. We do not rehook another transfer if the device instance is shutting down or + if the transfer was aborted by the class. */ + if ((hid -> ux_host_class_hid_state == UX_HOST_CLASS_INSTANCE_SHUTDOWN) || + (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_ABORT)) + + /* We do not proceed. */ + return; + + else + { + + /* Reactivate the HID interrupt pipe. */ + _ux_host_stack_transfer_request(transfer_request); + + /* We do not proceed. */ + return; + } + } + + /* Get the client instance attached to the HID. */ + hid_client = hid -> ux_host_class_hid_client; + + /* Get the pointer to the report buffer in the transfer request. */ + report_buffer = transfer_request -> ux_transfer_request_data_pointer; + + /* We know this incoming report is for the Input report. */ + hid_report = hid -> ux_host_class_hid_parser.ux_host_class_hid_parser_input_report; + + /* initialize some of the callback structure which are generic to any + reporting method. */ + callback.ux_host_class_hid_report_callback_client = hid_client; + callback.ux_host_class_hid_report_callback_id = hid_report -> ux_host_class_hid_report_id; + + /* For this report to be used, the HID client must have registered + the report. We check the call back function. */ + if (hid_report -> ux_host_class_hid_report_callback_function != UX_NULL) + { + + /* The report is now in memory in a raw format the application may desire to handle it that way! */ + if (hid_report -> ux_host_class_hid_report_callback_flags & UX_HOST_CLASS_HID_REPORT_RAW) + { + + /* Put the length of the report in raw form in the callers callback structure. */ + callback.ux_host_class_hid_report_callback_actual_length = transfer_request -> ux_transfer_request_actual_length; + callback.ux_host_class_hid_report_callback_buffer = report_buffer; + + /* Build the callback structure status. */ + callback.ux_host_class_hid_report_callback_status = status; + + /* Set the flags to indicate the type of report. */ + callback.ux_host_class_hid_report_callback_flags = hid_report -> ux_host_class_hid_report_callback_flags; + + /* Call the report owner. */ + hid_report -> ux_host_class_hid_report_callback_function(&callback); + } + else + { + + /* The report may be decompressed, buffer length is based on number of items in report. + Each item is a pair of words (usage and the value itself), so the required decompress memory for each + item is 4 (word size) * 2 (number of word) = 8 bytes. + To accelerate we shift number of item by 3 to get the result. */ + if (UX_OVERFLOW_CHECK_MULC_ULONG(hid_report->ux_host_class_hid_report_number_item, 8)) + client_buffer = UX_NULL; + else + { + client_report.ux_host_class_hid_client_report_length = hid_report->ux_host_class_hid_report_number_item << 3; + + /* We need to allocate some memory to build the decompressed report. */ + client_buffer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, client_report.ux_host_class_hid_client_report_length); + } + + /* Check completion status. */ + if (client_buffer == UX_NULL) + { + /* We have an error of memory, do not proceed */ + status = UX_MEMORY_INSUFFICIENT; + } + else + { + + /* We need to build a client structure to be used by the decompression engine. */ + client_report.ux_host_class_hid_client_report_buffer = client_buffer; + client_report.ux_host_class_hid_client_report_actual_length = 0; + client_report.ux_host_class_hid_client_report = hid_report; + + /* The report buffer must be parsed and decompressed into the local buffer. */ + _ux_host_class_hid_report_decompress(hid, &client_report, report_buffer, transfer_request -> ux_transfer_request_actual_length); + + /* The report may be decompressed and returned as individual Usages. */ + if (hid_report -> ux_host_class_hid_report_callback_flags & UX_HOST_CLASS_HID_REPORT_INDIVIDUAL_USAGE) + { + + /* Now, we need to call the HID client call back function with a usage/value couple. */ + hid_field = hid_report -> ux_host_class_hid_report_field; + + /* Set the flags to indicate the type of report (usage/value couple). */ + callback.ux_host_class_hid_report_callback_flags = hid_report -> ux_host_class_hid_report_callback_flags; + + /* The length of the buffer is irrelevant here so we reset it. */ + callback.ux_host_class_hid_report_callback_actual_length = 0; + + /* Scan all the fields and send each usage/value. */ + while(hid_field != UX_NULL) + { + + /* Build each report item. */ + for (field_report_count = 0; field_report_count < hid_field -> ux_host_class_hid_field_report_count; field_report_count++) + { + + /* Insert the usage and the report value into the callback structure. */ + callback.ux_host_class_hid_report_callback_usage = *client_report.ux_host_class_hid_client_report_buffer++; + callback.ux_host_class_hid_report_callback_value = *client_report.ux_host_class_hid_client_report_buffer++; + + /* Build the callback structure status. */ + callback.ux_host_class_hid_report_callback_status = status; + + /* Call the report owner */ + hid_report -> ux_host_class_hid_report_callback_function(&callback); + } + + /* Get the next field. */ + hid_field = hid_field -> ux_host_class_hid_field_next_field; + } + } + else + { + + /* Add the length actually valid in the caller's buffer. */ + callback.ux_host_class_hid_report_callback_actual_length = client_report.ux_host_class_hid_client_report_actual_length; + + /* Add the caller's buffer address. */ + callback.ux_host_class_hid_report_callback_buffer = client_report.ux_host_class_hid_client_report_buffer; + + /* Build the callback structure status. */ + callback.ux_host_class_hid_report_callback_status = status; + + /* Set the flags to indicate the type of report. */ + callback.ux_host_class_hid_report_callback_flags = hid_report -> ux_host_class_hid_report_callback_flags; + + /* Call the report owner. */ + hid_report -> ux_host_class_hid_report_callback_function(&callback); + } + + /* Free the memory resource we used. */ + _ux_utility_memory_free(client_buffer); + } + } + } + + /* Check latest status. */ + if (status != UX_SUCCESS) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + + /* Reactivate the HID interrupt pipe. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check latest status. */ + if (status != UX_SUCCESS) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_activate.c b/common/usbx_host_classes/src/ux_host_class_hub_activate.c new file mode 100644 index 0000000..af25734 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_activate.c @@ -0,0 +1,172 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs the enumeration of the HUB. The HUB */ +/* descriptor is read, the interrupt endpoint activated, power is set */ +/* to the downstream ports and the HUB instance will be awaken when */ +/* there is a status change on the HUB or one of the ports. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_configure Configure HUB */ +/* _ux_host_class_hub_descriptor_get Get descriptor */ +/* _ux_host_class_hub_interrupt_endpoint_start */ +/* Start interrupt endpoint */ +/* _ux_host_class_hub_ports_power Power ports */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy class instance */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_create Create semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_DEVICE *device; +UX_HOST_CLASS_HUB *hub; +UINT status; + + + /* We need to make sure that the enumeration thread knows about at least + one active HUB instance and the function to call when the thread + is awaken. */ + _ux_system_host -> ux_system_host_enum_hub_function = _ux_host_class_hub_change_detect; + + /* The HUB is always activated by the device descriptor and not the + instance descriptor. */ + device = (UX_DEVICE *) command -> ux_host_class_command_container; + + /* Instantiate this HUB class. */ + hub = (UX_HOST_CLASS_HUB *) _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS_HUB)); + if (hub == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance. */ + hub -> ux_host_class_hub_class = command -> ux_host_class_command_class_ptr; + + /* Store the class container into this instance. */ + hub -> ux_host_class_hub_class = command -> ux_host_class_command_class_ptr; + + /* Store the device container instance in the HUB instance, this is for + the class instance when it needs to talk to the USBX stack. */ + hub -> ux_host_class_hub_device = device; + + /* Configure the HUB. */ + status = _ux_host_class_hub_configure(hub); + if (status == UX_SUCCESS) + { + + /* Get the HUB descriptor. */ + status = _ux_host_class_hub_descriptor_get(hub); + if (status == UX_SUCCESS) + { + + /* Power up the HUB downstream ports. This function always returns + success since we may be dealing with multiple ports. */ + _ux_host_class_hub_ports_power(hub); + + /* Search the HUB interrupt endpoint and start it. */ + status = _ux_host_class_hub_interrupt_endpoint_start(hub); + if (status == UX_SUCCESS) + { + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(hub -> ux_host_class_hub_class, (VOID *) hub); + + /* Store the instance in the device container, this is for the USBX stack + when it needs to invoke the class. */ + device -> ux_device_class_instance = (VOID *) hub; + + /* Mark the HUB as live now. */ + hub -> ux_host_class_hub_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, hub -> ux_host_class_hub_class, (VOID *) hub); + } + + /* Return success. */ + return(UX_SUCCESS); + } + } + } + + /* We get here when an error occurred. */ + + /* Free the hub instance. */ + _ux_utility_memory_free(hub); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HUB_ACTIVATE, hub, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, hub, 0, 0, 0) + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_change_detect.c b/common/usbx_host_classes/src/ux_host_class_hub_change_detect.c new file mode 100644 index 0000000..265a1ec --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_change_detect.c @@ -0,0 +1,118 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_change_detect PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the enumeration thread when there has */ +/* been activity on the HUB. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_change_process Process HUB change */ +/* _ux_host_stack_class_get Get class */ +/* _ux_host_stack_class_instance_get Get class instance */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hub_change_detect(VOID) +{ + +UX_HOST_CLASS *class; +UX_HOST_CLASS_HUB *hub; +UINT status; +UINT class_index; + + /* Get the class container first. */ + _ux_host_stack_class_get(_ux_system_host_class_hub_name, &class); + + /* We start with the first index of the class instance. */ + class_index = 0; + + /* We have found the class, now parse the instances. */ + do + { + + /* Get class instance. */ + status = _ux_host_stack_class_instance_get(class, class_index++, (VOID **) &hub); + + /* Check completion status. */ + if (status == UX_SUCCESS) + { + + /* We have found an instance of a HUB, check if it is live and if the HUB has + detected a change before we proceed. */ + if (hub -> ux_host_class_hub_change_semaphore != 0) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HUB_CHANGE_DETECT, hub, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Call the HUB function that will diagnose the origin of the change. */ + _ux_host_class_hub_change_process(hub); + + /* Decrement the HUB instance semaphore change so we don't get awaken again. */ + hub -> ux_host_class_hub_change_semaphore--; + } + } + } while (status == UX_SUCCESS); + + /* We have parsed all the HUB instances. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_change_process.c b/common/usbx_host_classes/src/ux_host_class_hub_change_process.c new file mode 100644 index 0000000..6fd50c5 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_change_process.c @@ -0,0 +1,115 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Hub Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_change_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the topology thread when there has been */ +/* activity on the HUB. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_port_change_process Port change process */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_short_get Get 16-bit word */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_change_process(UX_HOST_CLASS_HUB *hub) +{ + +UX_TRANSFER *transfer_request; +USHORT port_status_change_bits; +UINT port_index; +UINT status; + + + /* Now get the transfer_request attached to the interrupt endpoint. */ + transfer_request = &hub -> ux_host_class_hub_interrupt_endpoint -> ux_endpoint_transfer_request; + + /* The interrupt pipe buffer contains the status change for each of the ports + the length of the buffer can be 1 or 2 depending on the number of ports. + Usually, since HUBs can be bus powered the maximum number of ports is 4. + We must be taking precautions on how we read the buffer content for + big endian machines. */ + if (transfer_request -> ux_transfer_request_actual_length == 1) + port_status_change_bits = (USHORT) *transfer_request -> ux_transfer_request_data_pointer; + else + port_status_change_bits = (USHORT)_ux_utility_short_get(transfer_request -> ux_transfer_request_data_pointer); + + /* Scan all bits and report the change on each port. */ + for (port_index = 1; port_index <= hub -> ux_host_class_hub_descriptor.bNbPorts; port_index++) + { + + if (port_status_change_bits & (1< ux_transfer_request_actual_length = 0; + + /* Resend the request to the stack. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Return completion status. */ + return(status); +} diff --git a/common/usbx_host_classes/src/ux_host_class_hub_configure.c b/common/usbx_host_classes/src/ux_host_class_hub_configure.c new file mode 100644 index 0000000..f5efdf5 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_configure.c @@ -0,0 +1,183 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to the */ +/* HUB. Once the HUB is configured, its interface will be activated */ +/* and all the endpoints enumerated (1 interrupt endpoint in the case */ +/* of the HUB). */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_device_configuration_get Get device configuration */ +/* _ux_host_stack_device_configuration_select */ +/* Select device configuration */ +/* _ux_host_stack_configuration_interface_get */ +/* Get interface */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_configure(UX_HOST_CLASS_HUB *hub) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_DEVICE *device; +UX_DEVICE *parent_device; +UX_ENDPOINT *control_endpoint; +UCHAR *device_status_data; +UX_TRANSFER *transfer_request; + + + /* A HUB normally has one configuration. So retrieve the 1st configuration + only. */ + _ux_host_stack_device_configuration_get(hub -> ux_host_class_hub_device, 0, &configuration); + + /* Get the device container for this configuration. */ + device = configuration -> ux_configuration_device; + + /* Get the parent container for this device. */ + parent_device = device -> ux_device_parent; + + /* To find the true source of the HUB power source, we need to do a GET_STATUS of + the device. */ + control_endpoint = &device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Allocate a buffer for the device status: 2 bytes. */ + device_status_data = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 2); + if (device_status_data == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Create a transfer_request for the GET_STATUS request, 2 bytes are returned. */ + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_data_pointer = device_status_data; + transfer_request -> ux_transfer_request_function = UX_GET_STATUS; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check the status and the length of the data returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 2)) + { + + /* The data returned is good, now analyze power source. */ + if (*device_status_data & UX_STATUS_DEVICE_SELF_POWERED) + device -> ux_device_power_source = UX_DEVICE_SELF_POWERED; + else + device -> ux_device_power_source = UX_DEVICE_BUS_POWERED; + + /* Free the buffer resource now. */ + _ux_utility_memory_free(device_status_data); + } + else + { + + /* Free the buffer resource now. */ + _ux_utility_memory_free(device_status_data); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, hub, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_CONNECTION_INCOMPATIBLE); + } + + /* Check the HUB power source and check the parent power source for + incompatible connections. */ + if (hub -> ux_host_class_hub_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* If the device is NULL, the parent is the root HUB and we don't have to worry + if the parent is not the root HUB, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, hub, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration. */ + status = _ux_host_stack_device_configuration_select(configuration); + + /* If the operation went well, the HUB default alternate setting for the HUB interface is + active and the interrupt endpoint is now enabled. We have to memorize the first interface + since the interrupt endpoint is hooked to it. */ + status = _ux_host_stack_configuration_interface_get(configuration, 0, 0, &hub -> ux_host_class_hub_interface); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_deactivate.c b/common/usbx_host_classes/src/ux_host_class_hub_deactivate.c new file mode 100644 index 0000000..ed4ef2d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_deactivate.c @@ -0,0 +1,151 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the HUB has been */ +/* removed from the bus either directly or indirectly. The interrupt */ +/* pipe will be destroyed and the instance removed. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy class instance */ +/* _ux_host_stack_device_remove Remove device */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort transfer */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_utility_thread_schedule_other Schedule other threads */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_HUB *hub; +UX_HCD *hcd; +UX_TRANSFER *transfer_request; +UINT port_index; + + + /* Get the instance to the class. */ + hub = (UX_HOST_CLASS_HUB *) command -> ux_host_class_command_instance; + + /* Get the HCD used by this instance. */ + hcd = hub -> ux_host_class_hub_device -> ux_device_hcd; + + /* The HUB is being shut down. */ + hub -> ux_host_class_hub_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* We need to abort transactions on the interrupt pipe. */ + _ux_host_stack_endpoint_transfer_abort(hub -> ux_host_class_hub_interrupt_endpoint); + + /* Each device which is downstream on the HUB ports must be removed. */ + for (port_index = 1; port_index <= hub -> ux_host_class_hub_descriptor.bNbPorts; port_index++) + { + + /* Is there a device on this port? */ + if (hub -> ux_host_class_hub_port_state & (1UL << port_index)) + { + + /* The stack will remove the device and its resources. */ + _ux_host_stack_device_remove(hcd, hub -> ux_host_class_hub_device, port_index); + } + } + + /* If the Hub class instance has a interrupt pipe with a data payload associated with it + it must be freed. First get the transfer request. */ + transfer_request = &hub -> ux_host_class_hub_interrupt_endpoint -> ux_endpoint_transfer_request; + + /* Abort the data transfer on the interrupt endpoint. */ + _ux_host_stack_endpoint_transfer_abort(hub -> ux_host_class_hub_interrupt_endpoint); + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Then de allocate the memory. */ + _ux_utility_memory_free(transfer_request -> ux_transfer_request_data_pointer); + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(hub -> ux_host_class_hub_class, (VOID *) hub); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, hub -> ux_host_class_hub_class, (VOID *) hub); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HUB_DEACTIVATE, hub, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(hub); + + /* Free the memory block used by the class. */ + _ux_utility_memory_free(hub); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_descriptor_get.c b/common/usbx_host_classes/src/ux_host_class_hub_descriptor_get.c new file mode 100644 index 0000000..449e8a6 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_descriptor_get.c @@ -0,0 +1,183 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_descriptor_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the HUB descriptor. This descriptor contains */ +/* the number of downstream ports and the power characteristics of the */ +/* HUB (self powered or bus powered). */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_descriptor_get(UX_HOST_CLASS_HUB *hub) +{ + +UCHAR *descriptor; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +ULONG port_index; + + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hub -> ux_host_class_hub_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the descriptor. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HUB_DESCRIPTOR_LENGTH); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Create a transfer request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = UX_HUB_DESCRIPTOR_LENGTH; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HUB_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = (UX_HUB_DESCRIPTOR_ITEM << 8); + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Did the transfer succeed? */ + if (status == UX_SUCCESS) + { + + /* Is the length valid? */ + if (transfer_request -> ux_transfer_request_actual_length == UX_HUB_DESCRIPTOR_LENGTH) + { + + /* Parse the device descriptor and create the local descriptor. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_hub_descriptor_structure, UX_HUB_DESCRIPTOR_ENTRIES, + (UCHAR *) &hub -> ux_host_class_hub_descriptor); + + /* Check the protocol used by the HUB. This will indicate if the HUB supports multiple TTs in high speed mode. */ + switch (hub -> ux_host_class_hub_device -> ux_device_descriptor.bDeviceProtocol) + { + + case UX_HOST_CLASS_HUB_PROTOCOL_FS: + + /* In the case of full speed hub, there are no TTs to declare */ + break; + + + case UX_HOST_CLASS_HUB_PROTOCOL_SINGLE_TT: + + /* In a single TT state, all the downstream ports report to the same + TT and share the 1.1 USB segment bandwidth. This is a very crude + but working method, we simply set all the ports bits to the first + TT. */ + hub -> ux_host_class_hub_device -> ux_device_hub_tt[0].ux_hub_tt_port_mapping = UX_TT_MASK; + hub -> ux_host_class_hub_device -> ux_device_hub_tt[0].ux_hub_tt_max_bandwidth = UX_TT_BANDWIDTH; + break; + + + case UX_HOST_CLASS_HUB_PROTOCOL_MULTIPLE_TT: + + /* In the case of multiple TTs, each downstream port can sustain the USB 1.1 + max bandwidth and therefore we allocate one TT per port with that bandwidth. */ + for (port_index = 0; port_index < hub -> ux_host_class_hub_descriptor.bNbPorts;port_index++) + { + + hub -> ux_host_class_hub_device -> ux_device_hub_tt[port_index].ux_hub_tt_port_mapping = (ULONG)(1 << port_index); + hub -> ux_host_class_hub_device -> ux_device_hub_tt[port_index].ux_hub_tt_max_bandwidth = UX_TT_BANDWIDTH; + } + break; + + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We should never get here. In this case the protocol value of the HUB is illegal. */ + status = UX_DESCRIPTOR_CORRUPTED; + } + } + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* The descriptor must be corrupted if we got an invalid length. */ + status = UX_DESCRIPTOR_CORRUPTED; + } + } + + /* Free the memory for the descriptor. */ + _ux_utility_memory_free(descriptor); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_entry.c b/common/usbx_host_classes/src/ux_host_class_hub_entry.c new file mode 100644 index 0000000..991612a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_entry.c @@ -0,0 +1,125 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the HUB class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* device on the bus or when there is a device extraction. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_activate Activate HUB class */ +/* _ux_host_class_hub_deactivate Deactivate HUB class */ +/* */ +/* CALLED BY */ +/* */ +/* Host Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if ((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) && + (command -> ux_host_class_command_class == UX_HOST_CLASS_HUB_CLASS)) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_hub_activate(command); + + /* Return completion status. */ + return(status); + + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted */ + status = _ux_host_class_hub_deactivate(command); + + /* Return completion status. */ + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error status. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} diff --git a/common/usbx_host_classes/src/ux_host_class_hub_feature.c b/common/usbx_host_classes/src/ux_host_class_hub_feature.c new file mode 100644 index 0000000..fbf64d3 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_feature.c @@ -0,0 +1,106 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_feature PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will send a command to the HUB on a specific port. */ +/* The commands can be SET_FEATURE or CLEAR_FEATURE. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* port Port number */ +/* command Command to send */ +/* feature Feature to send */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_feature(UX_HOST_CLASS_HUB *hub, UINT port, UINT command, UINT function) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT target; +UINT status; + + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hub -> ux_host_class_hub_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* The target is DEVICE for the HUB and OTHER for the downstream ports. */ + if (port == 0) + target = UX_REQUEST_TARGET_DEVICE; + else + target = UX_REQUEST_TARGET_OTHER; + + /* Create a transfer request for the SET_FEATURE or CLEAR_FEATURE request. */ + transfer_request -> ux_transfer_request_function = command; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | target; + transfer_request -> ux_transfer_request_value = function; + transfer_request -> ux_transfer_request_index = port; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_hub_change_process.c b/common/usbx_host_classes/src/ux_host_class_hub_hub_change_process.c new file mode 100644 index 0000000..b386998 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_hub_change_process.c @@ -0,0 +1,79 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_hub_change_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when there is a change on the HUB itself */ +/* (not a HUB port!). */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_hub_change_process(UX_HOST_CLASS_HUB *hub) +{ + + UX_PARAMETER_NOT_USED(hub); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_interrupt_endpoint_start.c b/common/usbx_host_classes/src/ux_host_class_hub_interrupt_endpoint_start.c new file mode 100644 index 0000000..e82a0f2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_interrupt_endpoint_start.c @@ -0,0 +1,139 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_interrupt_endpoint_start PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function search for the handle of the only interrupt endpoint */ +/* in the default alternate setting of the HUB interface. The */ +/* interrupt endpoint should always be there. When it is located, the */ +/* first transfer for this endpoint is made. The HUB will report status*/ +/* changes on this pipe. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_endpoint_get Get endpoint of interface */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_interrupt_endpoint_start(UX_HOST_CLASS_HUB *hub) +{ + +UINT status; +UX_TRANSFER *transfer_request; + + + /* Search the interrupt endpoint. It is attached to the interface container. */ + status = _ux_host_stack_interface_endpoint_get(hub -> ux_host_class_hub_interface, 0, &hub -> ux_host_class_hub_interrupt_endpoint); + + /* Check completion status. */ + if (status != UX_SUCCESS) + return(status); + + /* Do a sanity check on the nature of the endpoint. Must be interrupt and its direction must be IN. */ + if (((hub -> ux_host_class_hub_interrupt_endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((hub -> ux_host_class_hub_interrupt_endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)) + { + + /* The endpoint is correct, fill in the transfer_request with the length requested for this endpoint. */ + transfer_request = &hub -> ux_host_class_hub_interrupt_endpoint -> ux_endpoint_transfer_request; + transfer_request -> ux_transfer_request_requested_length = hub -> ux_host_class_hub_interrupt_endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + transfer_request -> ux_transfer_request_actual_length = 0; + + /* Since this transfer_request has a callback, we need the HUB instance to be stored in the transfer request. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) hub; + + /* This transfer request always has the IN direction. */ + hub -> ux_host_class_hub_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* Interrupt transactions have a completion routine. */ + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_hub_transfer_request_completed; + + /* Obtain a buffer for this transaction. The buffer will always be reused. */ + transfer_request -> ux_transfer_request_data_pointer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + transfer_request -> ux_transfer_request_requested_length); + + /* Check the memory pointer. */ + if (transfer_request -> ux_transfer_request_data_pointer == UX_NULL) + { + + /* Clear the interrupt endpoint. */ + hub -> ux_host_class_hub_interrupt_endpoint = UX_NULL; + + /* Return error. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Send the request to the stack. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Return completion status. */ + return(status); + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, hub -> ux_host_class_hub_interrupt_endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error. */ + return(UX_ENDPOINT_HANDLE_UNKNOWN); +} diff --git a/common/usbx_host_classes/src/ux_host_class_hub_port_change_connection_process.c b/common/usbx_host_classes/src/ux_host_class_hub_port_change_connection_process.c new file mode 100644 index 0000000..20a8831 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_port_change_connection_process.c @@ -0,0 +1,220 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_port_change_connection_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will process a connection change on the port. This */ +/* indicates that a device has been attached to the port. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* port Port number */ +/* port_status Port status */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_feature Set HUB feature */ +/* _ux_host_class_hub_port_reset Reset port */ +/* _ux_host_class_hub_status_get Get status */ +/* _ux_host_stack_new_device_create Create new device */ +/* _ux_host_stack_device_remove Remove device */ +/* _ux_utility_delay_ms Thread sleep */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hub_port_change_connection_process(UX_HOST_CLASS_HUB *hub, UINT port, UINT port_status) +{ + +UINT device_speed; +UINT device_enumeration_retry; +USHORT port_power; +UINT status; +UX_HCD *hcd; +USHORT local_port_status; +USHORT local_port_change; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HUB_PORT_CHANGE_CONNECTION_PROCESS, hub, port, port_status, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Get the HCD used by this instance. */ + hcd = hub -> ux_host_class_hub_device -> ux_device_hcd; + + /* If there is a device attached on this HUB, there is a new device and it should + be enumerated. */ + if (port_status & UX_HOST_CLASS_HUB_PORT_STATUS_CONNECTION) + { + + /* Check if there was a previous device already attached on this port. This may happen when a device + disconnects and reconnect very quickly before the hub has a chance to poll the port state. In this + case we do a device removal before doing a device connection. */ + if (hub -> ux_host_class_hub_port_state & (UINT)(1 << port)) + { + + /* There was a device attached previously. Perform a removal. */ + status = _ux_host_stack_device_remove(hcd, hub -> ux_host_class_hub_device, port); + + } + else + + /* Mark device connection. */ + hub -> ux_host_class_hub_port_state |= (UINT)(1 << port); + + /* Tell the hub to clear the change bit for this port so that we do + not process the same change event again. */ + _ux_host_class_hub_feature(hub, port, UX_CLEAR_FEATURE, UX_HOST_CLASS_HUB_C_PORT_CONNECTION); + + /* Some devices are known to fail on the first try. */ + for (device_enumeration_retry = 0; device_enumeration_retry < UX_HOST_CLASS_HUB_ENUMERATION_RETRY; device_enumeration_retry++) + { + + /* Wait for debounce. */ + _ux_utility_delay_ms(UX_HOST_CLASS_HUB_ENUMERATION_DEBOUNCE_DELAY); + + /* The port must be reset. */ + status = _ux_host_class_hub_port_reset(hub, port); + if (status != UX_SUCCESS) + return; + + /* Reset succeeded, so perform a new port status after reset to force speed reevaluation. */ + status = _ux_host_class_hub_status_get(hub, port, &local_port_status, &local_port_change); + if (status != UX_SUCCESS) + return; + + /* Device connected. Get the device speed. */ + if (local_port_status & UX_HOST_CLASS_HUB_PORT_STATUS_LOW_SPEED) + device_speed = UX_LOW_SPEED_DEVICE; + else + { + + if (local_port_status & UX_HOST_CLASS_HUB_PORT_STATUS_HIGH_SPEED) + device_speed = UX_HIGH_SPEED_DEVICE; + else + device_speed = UX_FULL_SPEED_DEVICE; + } + + /* Decide how much power this device can draw. This depends if the HUB is self + powered or bus powered. */ + if (hub -> ux_host_class_hub_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + + /* Hub is bus powered. */ + port_power = UX_MAX_BUS_POWER; + else + + /* Hub is self powered. */ + port_power = UX_MAX_SELF_POWER; + + /* Wait for reset recovery. */ + _ux_utility_delay_ms(UX_HOST_CLASS_HUB_ENUMERATION_RESET_RECOVERY_DELAY); + + /* Perform the device creation. */ + status = _ux_host_stack_new_device_create(hub -> ux_host_class_hub_device -> ux_device_hcd, + hub -> ux_host_class_hub_device, + port, device_speed, port_power); + + /* Check return status. */ + if (status == UX_SUCCESS) + { + + /* Successful device creation. */ + /* Just return. */ + return; + } + else if (device_enumeration_retry < UX_HOST_CLASS_HUB_ENUMERATION_RETRY - 1) + { + + /* Simulate remove to free allocated resources before retry. */ + _ux_host_stack_device_remove(hcd, hub -> ux_host_class_hub_device, port); + + /* Wait for a while. */ + _ux_utility_delay_ms(UX_HOST_CLASS_HUB_ENUMERATION_RETRY_DELAY); + } + } + + /* If we get here, the device did not enumerate completely. */ + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_ROOT_HUB, UX_DEVICE_ENUMERATION_FAILURE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DEVICE_ENUMERATION_FAILURE, port, 0, 0, UX_TRACE_ERRORS, 0, 0) + } + else + { + + /* Check if there was a no previous device attached on this port. */ + if ((hub -> ux_host_class_hub_port_state & (UINT)(1 << port))) + { + /* Mark device disconnection. */ + hub -> ux_host_class_hub_port_state &= (UINT)~(1 << port); + + /* We get here when there is a device extraction. */ + status = _ux_host_stack_device_remove(hcd, hub -> ux_host_class_hub_device, port); + } + + /* The port should be disabled now. Power is still applied. */ + status = _ux_host_class_hub_feature(hub, port, UX_CLEAR_FEATURE, UX_HOST_CLASS_HUB_PORT_ENABLE); + + /* We must clear the enable change condition so that we don't get awaken again. */ + _ux_host_class_hub_feature(hub, port, UX_CLEAR_FEATURE, UX_HOST_CLASS_HUB_C_PORT_ENABLE); + + /* We must clear the connection change condition so that we don't get awaken again. */ + _ux_host_class_hub_feature(hub, port, UX_CLEAR_FEATURE, UX_HOST_CLASS_HUB_C_PORT_CONNECTION); + } + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_port_change_enable_process.c b/common/usbx_host_classes/src/ux_host_class_hub_port_change_enable_process.c new file mode 100644 index 0000000..7a056e2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_port_change_enable_process.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_port_change_enable_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will process a enable condition change. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* port Port number */ +/* port_status Port status */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_feature Set HUB feature */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hub_port_change_enable_process(UX_HOST_CLASS_HUB *hub, UINT port, UINT port_status) +{ + + UX_PARAMETER_NOT_USED(port_status); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HUB_PORT_CHANGE_ENABLE_PROCESS, hub, port, port_status, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Here we simply clear the condition so that we don't get awaken again. */ + _ux_host_class_hub_feature(hub, port, UX_CLEAR_FEATURE, UX_HOST_CLASS_HUB_C_PORT_ENABLE); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_port_change_over_current_process.c b/common/usbx_host_classes/src/ux_host_class_hub_port_change_over_current_process.c new file mode 100644 index 0000000..ad198bd --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_port_change_over_current_process.c @@ -0,0 +1,89 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_port_change_over_current_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will process a over current condition change. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* port Port number */ +/* port_status Port status */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_feature Set HUB feature */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hub_port_change_over_current_process(UX_HOST_CLASS_HUB *hub, UINT port, UINT port_status) +{ + + UX_PARAMETER_NOT_USED(port_status); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HUB_PORT_CHANGE_OVER_CURRENT_PROCESS, hub, port, port_status, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Here we simply clear the condition so that we don't get awaken again. */ + _ux_host_class_hub_feature(hub, port, UX_CLEAR_FEATURE, UX_HOST_CLASS_HUB_C_PORT_OVER_CURRENT); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_OVER_CURRENT_CONDITION); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_port_change_process.c b/common/usbx_host_classes/src/ux_host_class_hub_port_change_process.c new file mode 100644 index 0000000..246db51 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_port_change_process.c @@ -0,0 +1,114 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_port_change_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will process a port change indication. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* port Port number */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_port_change_connection_process */ +/* Process connection */ +/* _ux_host_class_hub_port_change_enable_process */ +/* Enable process */ +/* _ux_host_class_hub_port_change_over_current_process */ +/* Change over current process */ +/* _ux_host_class_hub_port_change_reset_process */ +/* Reset process */ +/* _ux_host_class_hub_port_change_suspend_process */ +/* Suspend process */ +/* _ux_host_class_hub_status_get Get HUB status */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_port_change_process(UX_HOST_CLASS_HUB *hub, UINT port) +{ + +USHORT port_status; +USHORT port_change; +UINT status; + + + /* First step is to retrieve the status on the port with a GET_STATUS. */ + status = _ux_host_class_hub_status_get(hub, port, &port_status, &port_change); + if (status != UX_SUCCESS) + return(status); + + /* On return of the GET_STATUS, the port change field has been updated + check for each of the bits it may contain. */ + if (port_change & UX_HOST_CLASS_HUB_PORT_CHANGE_CONNECTION) + _ux_host_class_hub_port_change_connection_process(hub, port, port_status); + + if (port_change & UX_HOST_CLASS_HUB_PORT_CHANGE_ENABLE) + _ux_host_class_hub_port_change_enable_process(hub, port, port_status); + + if (port_change & UX_HOST_CLASS_HUB_PORT_CHANGE_SUSPEND) + _ux_host_class_hub_port_change_suspend_process(hub, port, port_status); + + if (port_change & UX_HOST_CLASS_HUB_PORT_CHANGE_OVER_CURRENT) + _ux_host_class_hub_port_change_over_current_process(hub, port, port_status); + + if (port_change & UX_HOST_CLASS_HUB_PORT_CHANGE_RESET) + _ux_host_class_hub_port_change_reset_process(hub, port, port_status); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_port_change_reset_process.c b/common/usbx_host_classes/src/ux_host_class_hub_port_change_reset_process.c new file mode 100644 index 0000000..733fbe8 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_port_change_reset_process.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_port_change_reset_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will process a reset condition change. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* port Port number */ +/* port_status Status of port */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_feature Set HUB class feature */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hub_port_change_reset_process(UX_HOST_CLASS_HUB *hub, UINT port, UINT port_status) +{ + + UX_PARAMETER_NOT_USED(port_status); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HUB_PORT_CHANGE_RESET_PROCESS, hub, port, port_status, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Here we simply clear the condition so that we don't get awaken again. */ + _ux_host_class_hub_feature(hub, port, UX_CLEAR_FEATURE, UX_HOST_CLASS_HUB_C_PORT_RESET); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_port_change_suspend_process.c b/common/usbx_host_classes/src/ux_host_class_hub_port_change_suspend_process.c new file mode 100644 index 0000000..270c954 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_port_change_suspend_process.c @@ -0,0 +1,86 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_port_change_suspend_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will process a suspend condition change. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* port Port number */ +/* port_status Status of port */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_feature Set HUB class feature */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hub_port_change_suspend_process(UX_HOST_CLASS_HUB *hub, UINT port, UINT port_status) +{ + + UX_PARAMETER_NOT_USED(port_status); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_HUB_PORT_CHANGE_SUSPEND_PROCESS, hub, port, port_status, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Here we simply clear the condition so that we don't get awaken again. */ + _ux_host_class_hub_feature(hub, port, UX_CLEAR_FEATURE, UX_HOST_CLASS_HUB_C_PORT_SUSPEND); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_port_reset.c b/common/usbx_host_classes/src/ux_host_class_hub_port_reset.c new file mode 100644 index 0000000..63106ba --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_port_reset.c @@ -0,0 +1,128 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_port_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will reset a downstream port of the HUB. When the */ +/* port is reset, the hardware logic of the HUB also enables it. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* port Port number */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_port_change_reset_process Reset HUB */ +/* _ux_host_class_hub_feature Set HUB class feature */ +/* _ux_host_class_hub_status_get Get HUB status */ +/* _ux_utility_delay_ms Thread sleep */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_port_reset(UX_HOST_CLASS_HUB *hub, UINT port) +{ + +UINT status; +UINT port_enable_retry; +USHORT port_status; +USHORT port_change; + + + /* Send the PORT_RESET command. */ + status = _ux_host_class_hub_feature(hub, port, UX_SET_FEATURE, UX_HOST_CLASS_HUB_PORT_RESET); + + /* Check the function result and update HUB status if there was a problem. */ + if (status != UX_SUCCESS) + return(status); + + /* We allow retrying of this as we may not get the port enable status bit + set on the first try. */ + port_enable_retry = UX_HOST_CLASS_HUB_ENABLE_RETRY_COUNT; + while (port_enable_retry--) + { + + /* Now get the status until we have a port enabled. */ + status = _ux_host_class_hub_status_get(hub, port, &port_status, &port_change); + if (status != UX_SUCCESS) + return(status); + + /* On return of the GET_STATUS, the port_change field has been updated. + Check for each of the bits it may contain. */ + if (port_change & UX_HOST_CLASS_HUB_PORT_CHANGE_RESET) + { + + /* The port has been successfully reset. */ + + /* Clear the RESET change bit. */ + _ux_host_class_hub_port_change_reset_process(hub, port, port_status); + + /* Return success. */ + return(UX_SUCCESS); + } + + /* We should wait a bit before retrying this operation. */ + _ux_utility_delay_ms(UX_HOST_CLASS_HUB_ENABLE_RETRY_DELAY); + } + + /* We get here when the port never reported RESET completion. */ + + /* Invoke error callback. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HUB, UX_PORT_RESET_FAILED); + + /* Return error. */ + return(UX_PORT_RESET_FAILED); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_ports_power.c b/common/usbx_host_classes/src/ux_host_class_hub_ports_power.c new file mode 100644 index 0000000..a10e458 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_ports_power.c @@ -0,0 +1,130 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_ports_power PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will power up each downstream port attached to the */ +/* HUB. There is a delay after powering up each port, otherwise we may */ +/* not detect device insertion. */ +/* */ +/* There are 3 port power modes: */ +/* */ +/* 1) Gang power: In this case we only power the first */ +/* port and all ports should be powered at */ +/* the same time */ +/* */ +/* 2) Individual power: In this case we power individually each */ +/* port */ +/* */ +/* 3) No power switching: In this case the power is applied to the */ +/* downstream ports when the upstream port */ +/* receives power. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_hub_feature Set HUB class feature */ +/* _ux_utility_delay_ms Thread sleep */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_ports_power(UX_HOST_CLASS_HUB *hub) +{ + +UINT nb_ports; +UINT port_index; +UINT status; + + + /* Check for the power management mode: no power switching. */ + if(hub -> ux_host_class_hub_descriptor.wHubCharacteristics & UX_HOST_CLASS_HUB_NO_POWER_SWITCHING) + return(UX_SUCCESS); + + /* All ports must be powered individually. */ + nb_ports = hub -> ux_host_class_hub_descriptor.bNbPorts; + + /* Perform the function to all ports: the port index starts from 1 as the port 0 is for the HUB. */ + for (port_index = 1; port_index <= nb_ports; port_index++) + { + + /* To apply port power, we send a SET_FEATURE to the port on the HUB. */ + status = _ux_host_class_hub_feature(hub, port_index, UX_SET_FEATURE, UX_HOST_CLASS_HUB_PORT_POWER); + + /* Check the function result and update HUB status if there was a problem. */ + if (status != UX_SUCCESS) + { + + /* Set the HUB status to not powered. */ + hub -> ux_host_class_hub_port_power &= (UINT)~(1 << port_index); + + } + else + { + + /* Now we need to wait for the power to be stable. */ + _ux_utility_delay_ms(((ULONG) (hub -> ux_host_class_hub_descriptor.bPwrOn2PwrGood) * 2)); + + /* Set the HUB status to powered. */ + hub -> ux_host_class_hub_port_power |= (UINT)(1 << port_index); + } + } + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_status_get.c b/common/usbx_host_classes/src/ux_host_class_hub_status_get.c new file mode 100644 index 0000000..fb165af --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_status_get.c @@ -0,0 +1,139 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_hub.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_status_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will do a GET_STATUS from the HUB. This function */ +/* retrieves the current status and the changed bits. */ +/* */ +/* INPUT */ +/* */ +/* hub Pointer to HUB class */ +/* port Port of device */ +/* port_status Destination for port status */ +/* port_change Destination for port change */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_short_get Get 16-bit word */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_hub_status_get(UX_HOST_CLASS_HUB *hub, UINT port, USHORT *port_status, USHORT *port_change) +{ + +UCHAR *port_data; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT target; +UINT status; + + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &hub -> ux_host_class_hub_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* The target is DEVICE for the HUB and OTHER for the downstream ports. */ + if (port == 0) + target = UX_REQUEST_TARGET_DEVICE; + else + target = UX_REQUEST_TARGET_OTHER; + + /* Allocate a buffer for the port status and change: 2 words. */ + port_data = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 4); + if(port_data == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Create a transfer request for the GET_STATUS request. */ + transfer_request -> ux_transfer_request_requested_length = 4; + transfer_request -> ux_transfer_request_data_pointer = port_data; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_HUB_GET_STATUS; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | target; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = port; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for error and completion of the transfer. */ + if (status == UX_SUCCESS) + { + + if (transfer_request -> ux_transfer_request_actual_length == 4) + { + + /* The 2 words are now in the buffer. We need to resolve their endianness + and report them as separate items to the called. */ + *port_status = (USHORT)_ux_utility_short_get(port_data); + *port_change = (USHORT)_ux_utility_short_get(port_data+2); + } + else + { + + /* Invalid length. Return error. */ + status = UX_TRANSFER_DATA_LESS_THAN_EXPECTED; + } + } + + /* Free the buffer resource now. */ + _ux_utility_memory_free(port_data); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_hub_transfer_request_completed.c b/common/usbx_host_classes/src/ux_host_class_hub_transfer_request_completed.c new file mode 100644 index 0000000..6addc55 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_hub_transfer_request_completed.c @@ -0,0 +1,125 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** HUB Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" +#include "ux_host_class_hub.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_hub_transfer_request_completed PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the completion thread when a transfer */ +/* request has been completed either because the transfer is */ +/* successful or there was an error. */ +/* */ +/* Because the HUB influences the topology of the USB, the insertion */ +/* or extraction of devices cannot be done during the transfer request */ +/* thread. We post a signal to the topology thread to wake up and */ +/* treat these changes on the HUB status. */ +/* */ +/* The interrupt pipe is not reactivated here. We will do this when */ +/* the topology thread has investigated the reason of the transfer */ +/* completion. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_semaphore_put Put the signaling semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* HUB Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_hub_transfer_request_completed(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_HUB *hub; + + + /* Get the class instance for this transfer request. */ + hub = (UX_HOST_CLASS_HUB *) transfer_request -> ux_transfer_request_class_instance; + + + /* Check the state of the transfer. If there is an error, we do not proceed with this report. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* We have an error. We do not rehook another transfer if the device instance is shutting down or + if the transfer was aborted by the class. */ + if ((hub -> ux_host_class_hub_state == UX_HOST_CLASS_INSTANCE_SHUTDOWN) || + (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_ABORT) || + (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_NO_ANSWER)) + + /* We do not proceed. */ + return; + else + + { + + /* Reactivate the HID interrupt pipe. */ + _ux_host_stack_transfer_request(transfer_request); + + /* We do not proceed. */ + return; + } + } + + /* We need to memorize which HUB instance has received a change signal. */ + hub -> ux_host_class_hub_change_semaphore++; + + /* Now we can set the semaphore, the enum thread will wake up and will + call the HUB instance which has a status change. */ + _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_activate.c b/common/usbx_host_classes/src/ux_host_class_pima_activate.c new file mode 100644 index 0000000..4c94a23 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_activate.c @@ -0,0 +1,176 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates the ACM instance, configure the device ... */ +/* */ +/* INPUT */ +/* */ +/* command Pima class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_configure Configure pima class */ +/* _ux_host_class_pima_endpoints_get Get endpoints of pima */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_pima_entry Entry of pima class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_INTERFACE *interface; +UX_HOST_CLASS_PIMA *pima; +UINT status; + + /* The PIMA class is always activated by the interface descriptor and not the + device descriptor. */ + interface = (UX_INTERFACE *) command -> ux_host_class_command_container; + + /* Obtain memory for this class instance. */ + pima = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS_PIMA)); + if (pima == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Allocate some DMA safe memory for sending/receiving headers. */ + pima -> ux_host_class_pima_container = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_CONTAINER_SIZE); + if (pima -> ux_host_class_pima_container == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + else + status = UX_SUCCESS; + + /* Allocate some DMA safe memory for receiving pima events. */ + if (status == UX_SUCCESS) + { + + pima -> ux_host_class_pima_event_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_AEI_MAX_LENGTH); + if (pima -> ux_host_class_pima_event_buffer == UX_NULL) + status = UX_MEMORY_INSUFFICIENT; + } + + /* Go on if no error. */ + if (status == UX_SUCCESS) + { + + /* Store the class container into this instance. */ + pima -> ux_host_class_pima_class = command -> ux_host_class_command_class_ptr; + + /* Store the interface container into the pima class instance. */ + pima -> ux_host_class_pima_interface = interface; + + /* Store the device container into the pima class instance. */ + pima -> ux_host_class_pima_device = interface -> ux_interface_configuration -> ux_configuration_device; + + /* This instance of the device must also be stored in the interface container. */ + interface -> ux_interface_class_instance = (VOID *) pima; + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(pima -> ux_host_class_pima_class, (VOID *) pima); + + /* Configure the pima. */ + status = _ux_host_class_pima_configure(pima); + } + + /* Get the pima endpoint(s). We will need to search for Bulk Out, Bulk In and interrupt endpoints. */ + if (status == UX_SUCCESS) + status = _ux_host_class_pima_endpoints_get(pima); + + /* Success things. */ + if (status == UX_SUCCESS) + { + + /* Mark the pima as live now. */ + pima -> ux_host_class_pima_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, pima -> ux_host_class_pima_class, (VOID *) pima); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_ACTIVATE, pima, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, pima, 0, 0, 0) + + /* Return success. */ + return(UX_SUCCESS); + } + + /* Free existing resources. */ + if (pima -> ux_host_class_pima_event_buffer) + { + _ux_host_stack_class_instance_destroy(pima -> ux_host_class_pima_class, (VOID *) pima); + interface -> ux_interface_class_instance = UX_NULL; + _ux_utility_memory_free(pima -> ux_host_class_pima_event_buffer); + } + + if (pima -> ux_host_class_pima_container) + _ux_utility_memory_free(pima -> ux_host_class_pima_container); + + _ux_utility_memory_free(pima); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_command.c b/common/usbx_host_classes/src/ux_host_class_pima_command.c new file mode 100644 index 0000000..2e63ddd --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_command.c @@ -0,0 +1,298 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_command PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will send a command to the PIMA device. */ +/* It will perform a data phase if necessary and the status phase. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* command pointer to command container */ +/* direction either IN or OUT */ +/* data_buffer buffer to be sent or received */ +/* data_length length of the buffer to send */ +/* or receive */ +/* max_payload_length maximum payload length */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_command(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_COMMAND *command, + ULONG direction, UCHAR *data_buffer, ULONG data_length, + ULONG max_payload_length) +{ + +UX_TRANSFER *transfer_request; +UCHAR *ptp_payload; +ULONG requested_length; +UINT status; + + /* We use the Bulk Out pipe for sending data out.. */ + transfer_request = &pima -> ux_host_class_pima_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Get the pointer to the ptp payload. */ + ptp_payload = pima -> ux_host_class_pima_container ; + + /* Calculate the requested length for this payload. */ + requested_length = UX_HOST_CLASS_PIMA_COMMAND_HEADER_SIZE + ((ULONG)sizeof(ULONG) * command -> ux_host_class_pima_command_nb_parameters); + + /* Fill the command container. First the length of the total header and payload. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_LENGTH, requested_length); + + /* Then the type of container : a command block here. */ + _ux_utility_short_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_TYPE, UX_HOST_CLASS_PIMA_CT_COMMAND_BLOCK); + + /* Now the command code to send. */ + _ux_utility_short_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_CODE, (USHORT)command -> ux_host_class_pima_command_operation_code); + + /* Save the operation code. */ + pima -> ux_host_class_pima_operation_code = command -> ux_host_class_pima_command_operation_code; + + /* Put the transaction ID. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_TRANSACTION_ID, + pima -> ux_host_class_pima_transaction_id++); + + /* Then fill in all the parameters. To make it quick we fill the 5 parameters, regardless + of the number contained in the command. But when the payload is transmitted, only the + relevant data is sent over the Bulk Out pipe. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_1, + command -> ux_host_class_pima_command_parameter_1); + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_2, + command -> ux_host_class_pima_command_parameter_2); + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_3, + command -> ux_host_class_pima_command_parameter_3); + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_4, + command -> ux_host_class_pima_command_parameter_4); + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_5, + command -> ux_host_class_pima_command_parameter_5); + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = ptp_payload; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Check for completion of transfer. If the transfer is partial, return to caller. + Partial transfer is not OK. */ + if (requested_length == transfer_request -> ux_transfer_request_actual_length) + { + + /* The command was sent successfully. Now examine the direction and check + if we need a data phase. If so which direction. */ + + switch (direction) + { + + /* No data phase, proceed to response directly. */ + case UX_HOST_CLASS_PIMA_DATA_PHASE_NONE : + + /* No error here. */ + status = UX_SUCCESS; + break; + + /* We need to transfer data IN. */ + case UX_HOST_CLASS_PIMA_DATA_PHASE_IN : + status = _ux_host_class_pima_read(pima, data_buffer, data_length, max_payload_length); + break; + + /* We need to transfer data OUT. */ + case UX_HOST_CLASS_PIMA_DATA_PHASE_OUT : + status = _ux_host_class_pima_write(pima, data_buffer, data_length, command -> ux_host_class_pima_command_operation_code, + max_payload_length); + break; + + default : + return(UX_ERROR); + + } + + /* Analyze the status. If no errors during the data phase proceed to response code. */ + if (status == UX_SUCCESS) + { + + /* We use the Bulk In pipe for receiving the response payload .. */ + transfer_request = &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Get the pointer to the ptp payload. */ + ptp_payload = pima -> ux_host_class_pima_container ; + + /* Calculate the requested length for this payload. */ + requested_length = UX_HOST_CLASS_PIMA_RESPONSE_HEADER_SIZE; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = ptp_payload; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Check to ensure this is a Response packet. */ + if (_ux_utility_short_get(ptp_payload + UX_HOST_CLASS_PIMA_RESPONSE_HEADER_TYPE) != + UX_HOST_CLASS_PIMA_CT_RESPONSE_BLOCK) + + /* We have a wrong packet. */ + return(UX_ERROR); + + /* Then get all the response parameters. */ + command -> ux_host_class_pima_command_parameter_1 = _ux_utility_long_get(ptp_payload + + UX_HOST_CLASS_PIMA_RESPONSE_HEADER_PARAMETER_1); + command -> ux_host_class_pima_command_parameter_2 = _ux_utility_long_get(ptp_payload + + UX_HOST_CLASS_PIMA_RESPONSE_HEADER_PARAMETER_2); + command -> ux_host_class_pima_command_parameter_3 = _ux_utility_long_get(ptp_payload + + UX_HOST_CLASS_PIMA_RESPONSE_HEADER_PARAMETER_3); + command -> ux_host_class_pima_command_parameter_4 = _ux_utility_long_get(ptp_payload + + UX_HOST_CLASS_PIMA_RESPONSE_HEADER_PARAMETER_4); + command -> ux_host_class_pima_command_parameter_5 = _ux_utility_long_get(ptp_payload + + UX_HOST_CLASS_PIMA_RESPONSE_HEADER_PARAMETER_5); + + /* We are done with the command. */ + return(UX_SUCCESS); + } + /* Return the error. */ + return(status); + } + else + /* Truncated command. */ + return(UX_TRANSFER_ERROR); + +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_configure.c b/common/usbx_host_classes/src/ux_host_class_pima_configure.c new file mode 100644 index 0000000..90411f9 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_configure.c @@ -0,0 +1,146 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to the */ +/* pima. Once the pima is configured, its interface will be */ +/* activated. The bulk endpoints (1 IN, 1 OUT ) and the interrupt */ +/* endpoint are enumerated. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get Get interface */ +/* _ux_host_stack_device_configuration_get Get configuration */ +/* _ux_host_stack_device_configuration_select Select configuration */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_pima_activate Pima class activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_configure(UX_HOST_CLASS_PIMA *pima) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_DEVICE *parent_device; + + + /* If the device has been configured already, we don't need to do it + again. */ + if (pima -> ux_host_class_pima_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* A pima normally has one configuration. So retrieve the 1st configuration + only. */ + status = _ux_host_stack_device_configuration_get(pima -> ux_host_class_pima_device, 0, &configuration); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, pima -> ux_host_class_pima_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check the pima power source and check the parent power source for + incompatible connections. */ + if (pima -> ux_host_class_pima_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* Get parent device pointer. */ + parent_device = pima -> ux_host_class_pima_device -> ux_device_parent; + + /* If the device is NULL, the parent is the root pima and we don't have to worry + if the parent is not the root pima, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, pima, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration. */ + status = _ux_host_stack_device_configuration_select(configuration); + if (status != UX_SUCCESS) + return(status); + + /* If the operation went well, the pima default alternate setting for the pima interface is + active and the interrupt endpoint is now enabled. We have to memorize the first interface since + the interrupt endpoint is hooked to it. */ + status = _ux_host_stack_configuration_interface_get(configuration, 0, 0, &pima -> ux_host_class_pima_interface); + if (status != UX_SUCCESS) + { + + /* Store the instance in the interface container, this is for the USB stack + when it needs to invoke the class. */ + pima -> ux_host_class_pima_interface -> ux_interface_class_instance = (VOID *) pima; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_deactivate.c b/common/usbx_host_classes/src/ux_host_class_pima_deactivate.c new file mode 100644 index 0000000..09fb56a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_deactivate.c @@ -0,0 +1,186 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the pima has been */ +/* removed from the bus either directly or indirectly. The bulk in\out */ +/* and interrupt pipes will be destroyed and the instance removed. */ +/* */ +/* INPUT */ +/* */ +/* command PIMA class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_pima_entry Entry of pima class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_PIMA *pima; +UX_HOST_CLASS_PIMA_SESSION *pima_session; +UX_TRANSFER *transfer_request; +UINT status; + + + /* Get the instance for this class. */ + pima = (UX_HOST_CLASS_PIMA *) command -> ux_host_class_command_instance; + + /* The pima is being shut down. */ + pima -> ux_host_class_pima_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&pima -> ux_host_class_pima_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* We come to this point when the device has been extracted. So there may have been a transaction + being scheduled. We make sure the transaction has been completed by the controller driver. + When the device is extracted, the controller tries multiple times the transaction and retires it + with a DEVICE_NOT_RESPONDING error code. + + First we take care of endpoint IN. */ + transfer_request = &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(pima -> ux_host_class_pima_bulk_in_endpoint); + + + /* Then endpoint OUT. */ + transfer_request = &pima -> ux_host_class_pima_bulk_out_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + + /* We need to abort transactions on the bulk Out pipe. We normally don't need that anymore. */ + _ux_host_stack_endpoint_transfer_abort(pima -> ux_host_class_pima_bulk_out_endpoint); + + + /* Then interrupt endpoint. */ + transfer_request = &pima -> ux_host_class_pima_interrupt_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + + /* We need to abort transactions on the Interrupt pipe. */ + _ux_host_stack_endpoint_transfer_abort(pima -> ux_host_class_pima_interrupt_endpoint); + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Free the header container buffer. */ + if (pima -> ux_host_class_pima_container != UX_NULL) + _ux_utility_memory_free(pima -> ux_host_class_pima_container); + + /* Free the event data buffer. */ + if (pima -> ux_host_class_pima_event_buffer != UX_NULL) + _ux_utility_memory_free(pima -> ux_host_class_pima_event_buffer); + + /* Get the pointer to the PIMA session. */ + pima_session = pima -> ux_host_class_pima_session; + + /* Was there a PIMA session ? */ + if(pima_session != UX_NULL) + { + /* Clean the PIMA session and free the storage ID buffer in the session if it is opened. */ + if ((pima_session -> ux_host_class_pima_session_magic == UX_HOST_CLASS_PIMA_MAGIC_NUMBER) && + (pima_session -> ux_host_class_pima_session_state == UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED)) + + { + + /* Reset the magic field. */ + pima_session -> ux_host_class_pima_session_magic = 0; + + /* Declare the session closed. */ + pima_session -> ux_host_class_pima_session_state = UX_HOST_CLASS_PIMA_SESSION_STATE_CLOSED; + + } + } + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(pima -> ux_host_class_pima_class, (VOID *) pima); + + /* Destroy the semaphore. */ + _ux_utility_semaphore_delete(&pima -> ux_host_class_pima_semaphore); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, pima -> ux_host_class_pima_class, (VOID *) pima); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_DEACTIVATE, pima, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(pima); + + /* Free the pima instance memory. */ + _ux_utility_memory_free(pima); + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_device_info_get.c b/common/usbx_host_classes/src/ux_host_class_pima_device_info_get.c new file mode 100644 index 0000000..5aa9be2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_device_info_get.c @@ -0,0 +1,351 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_device_info_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the device information block. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_device Device structure to fill */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* _ux_utility_descriptor_parse Unpack descriptor */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_free Free allocated memory */ +/* _ux_utility_short_get Get 16-bit value */ +/* _ux_utility_long_get Get 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_device_info_get(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_DEVICE *pima_device) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UCHAR *device_buffer; +UCHAR *device_pointer; +ULONG unicode_string_length; +ULONG array_length = 0; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_DEVICE_INFO_GET, pima, pima_device, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Issue command to get the device info. no parameter. */ + command.ux_host_class_pima_command_nb_parameters = 0; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_1 = 0; + command.ux_host_class_pima_command_parameter_2 = 0; + command.ux_host_class_pima_command_parameter_3 = 0; + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Then set the command to GET_DEVICE_INFO. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_GET_DEVICE_INFO; + + /* Allocate some DMA safe memory for receiving the device info block. */ + device_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_DEVICE_MAX_LENGTH); + if (device_buffer == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, UX_HOST_CLASS_PIMA_DATA_PHASE_IN , device_buffer, + UX_HOST_CLASS_PIMA_DEVICE_MAX_LENGTH, UX_HOST_CLASS_PIMA_DEVICE_MAX_LENGTH); + + /* Check the result. If the result is OK, the device info block was read properly. */ + if (status == UX_SUCCESS) + { + + /* Read and store the Standard Version field. */ + pima_device -> ux_host_class_pima_device_standard_version = _ux_utility_short_get(device_buffer + + UX_HOST_CLASS_PIMA_DEVICE_STANDARD_VERSION); + + /* Read and store the Vendor Extension ID . */ + pima_device -> ux_host_class_pima_device_vendor_extension_id = _ux_utility_long_get(device_buffer + + UX_HOST_CLASS_PIMA_DEVICE_VENDOR_EXTENSION_ID); + + /* Read and store the Vendor Extension Version . */ + pima_device -> ux_host_class_pima_device_vendor_extension_version = _ux_utility_long_get(device_buffer + + UX_HOST_CLASS_PIMA_DEVICE_VENDOR_EXTENSION_VERSION); + + + /* Copy the vendor extension descriptor. */ + device_pointer = device_buffer + UX_HOST_CLASS_PIMA_DEVICE_VENDOR_EXTENSION_DESC; + + /* Get the unicode string length. */ + unicode_string_length = (ULONG) *device_pointer; + + /* Check if the string can fit in our buffer. */ + if (unicode_string_length > UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH) + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the object description field. */ + _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_vendor_extension_desc, device_pointer, unicode_string_length); + + /* Point to the next field. */ + device_pointer += unicode_string_length + 1; + + /* Read and store the Functional Mode. */ + pima_device -> ux_host_class_pima_device_functional_mode = _ux_utility_short_get(device_pointer); + + /* Point to the next field. */ + device_pointer += sizeof(USHORT); + + /* Get the number of elements in array and compute total length. */ + array_length = (ULONG)sizeof(ULONG) + (_ux_utility_long_get(device_pointer) * 2); + + /* Ensure the array can fit in our buffer. */ + if (array_length > UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH) + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy the array of supported operations. */ + _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_operations_supported, device_pointer, array_length); + + /* Point to the next field. */ + device_pointer += array_length; + + /* Get the number of elements in array and compute total length. */ + array_length = (ULONG)sizeof(ULONG) + (_ux_utility_long_get(device_pointer) * 2); + + /* Ensure the array can fit in our buffer. */ + if (array_length > UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy the array of events supported. */ + _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_events_supported, device_pointer, array_length); + + /* Point to the next field. */ + device_pointer += array_length; + + /* Get the number of elements in array and compute total length. */ + array_length = (ULONG)sizeof(ULONG) + (_ux_utility_long_get(device_pointer) * 2); + + /* Ensure the array can fit in our buffer. */ + if (array_length > UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy the array of device properties. */ + _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_properties_supported, device_pointer, array_length); + + /* Point to the next field. */ + device_pointer += array_length; + + /* Get the number of elements in array and compute total length. */ + array_length = (ULONG)sizeof(ULONG) + (_ux_utility_long_get(device_pointer) * 2); + + /* Ensure the array can fit in our buffer. */ + if (array_length > UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy the array of capture formats. */ + _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_capture_formats, device_pointer, array_length); + + /* Point to the next field. */ + device_pointer += array_length; + + /* Get the number of elements in array and compute total length. */ + array_length = (ULONG)sizeof(ULONG) + (_ux_utility_long_get(device_pointer) * 2); + + /* Ensure the array can fit in our buffer. */ + if (array_length > UX_HOST_CLASS_PIMA_ARRAY_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy the array of supported operations. */ + _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_image_formats, device_pointer, array_length); + + /* Point to the next field. */ + device_pointer += array_length; + + /* Get the unicode string length. */ + unicode_string_length = (ULONG) *device_pointer; + + /* Ensure the string can fit in our buffer. */ + if (unicode_string_length > UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the manufacturer field. */ + _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_manufacturer, device_pointer, unicode_string_length); + + /* Point to the next field. */ + device_pointer += unicode_string_length + 1; + + /* Get the unicode string length. */ + unicode_string_length = (ULONG) *device_pointer ; + + /* Ensure the string can fit in our buffer. */ + if (unicode_string_length > UX_HOST_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the model date field. */ + _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_model, device_pointer, unicode_string_length); + + /* Point to the next field. */ + device_pointer += unicode_string_length + 1; + + /* Get the unicode string length. */ + unicode_string_length = (ULONG) *device_pointer ; + + /* Ensure the string can fit in our buffer. */ + if (unicode_string_length > UX_HOST_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the version field. */ + _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_version, device_pointer, unicode_string_length); + + /* Point to the next field. */ + device_pointer += unicode_string_length + 1; + + /* Get the unicode string length. */ + unicode_string_length = (ULONG) *device_pointer ; + + /* Ensure the string can fit in our buffer. */ + if (unicode_string_length > UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH) + + /* Return overflow error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + + /* Copy that string into the serial number field. */ + _ux_utility_memory_copy(pima_device -> ux_host_class_pima_device_serial_number, device_pointer, unicode_string_length); + + else + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Report error to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + } + } + + /* Free the original object info buffer. */ + _ux_utility_memory_free(device_buffer); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_device_reset.c b/common/usbx_host_classes/src/ux_host_class_pima_device_reset.c new file mode 100644 index 0000000..24cc876 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_device_reset.c @@ -0,0 +1,101 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_device_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function resets the device. */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_device_reset(UX_HOST_CLASS_PIMA *pima) +{ + +UX_TRANSFER *transfer_request; +UX_ENDPOINT *control_endpoint; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_DEVICE_RESET, pima, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &pima -> ux_host_class_pima_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Create a transfer_request for the CANCEL request. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PIMA_REQUEST_RESET_DEVICE; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Reset the session pointer if it was opened. A device reset closes the session. */ + pima -> ux_host_class_pima_session = UX_NULL; + + /* Return completion status. */ + return(status); + +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_pima_endpoints_get.c new file mode 100644 index 0000000..abbd09e --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_endpoints_get.c @@ -0,0 +1,233 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enables the bulk in bulk out and interrupt endpoints. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_pima_activate Activate pima class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_endpoints_get(UX_HOST_CLASS_PIMA *pima) +{ + +UINT status; +UINT endpoint_index; +UX_ENDPOINT *endpoint; +UX_TRANSFER *transfer_request; + + + + /* Search the bulk OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < pima -> ux_host_class_pima_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get interface endpoint. */ + status = _ux_host_stack_interface_endpoint_get(pima -> ux_host_class_pima_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the OUT direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + + /* We have found the bulk endpoint, save it. */ + pima -> ux_host_class_pima_bulk_out_endpoint = endpoint; + break; + } + } + } + + /* The bulk out endpoint is mandatory. */ + if (pima -> ux_host_class_pima_bulk_out_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, pima, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search the bulk IN endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < pima -> ux_host_class_pima_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + status = _ux_host_stack_interface_endpoint_get(pima -> ux_host_class_pima_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the bulk endpoint, save it. */ + pima -> ux_host_class_pima_bulk_in_endpoint = endpoint; + break; + } + } + } + + /* The bulk in endpoint is mandatory. */ + if (pima -> ux_host_class_pima_bulk_in_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, pima, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search the Interrupt endpoint. It is attached to the interface container of the control interface. It is not mandatory. */ + for (endpoint_index = 0; endpoint_index < pima -> ux_host_class_pima_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + status = _ux_host_stack_interface_endpoint_get(pima -> ux_host_class_pima_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is Interrupt and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the interrupt endpoint, save it. */ + pima -> ux_host_class_pima_interrupt_endpoint = endpoint; + + /* The endpoint is correct, Fill in the transfer request with the length requested for this endpoint. */ + transfer_request = &pima -> ux_host_class_pima_interrupt_endpoint -> ux_endpoint_transfer_request; + transfer_request -> ux_transfer_request_requested_length = pima -> ux_host_class_pima_interrupt_endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + transfer_request -> ux_transfer_request_actual_length = 0; + + /* The direction is always IN for the Pima interrupt endpoint. */ + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN; + + /* There is a callback function associated with the transfer request, so we need the class instance. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) pima; + + /* Interrupt transactions have a completion routine. */ + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_pima_notification; + + /* Obtain a buffer for this transaction. The buffer will always be reused. */ + transfer_request -> ux_transfer_request_data_pointer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + transfer_request -> ux_transfer_request_requested_length); + + /* Check memory allocation. */ + if (transfer_request -> ux_transfer_request_data_pointer != UX_NULL) + { + + /* The transfer on the interrupt endpoint can be started. */ + status = _ux_host_stack_transfer_request(transfer_request); + + } + + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We must return an error. */ + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + break; + } + } + } + + + /* All endpoints have been mounted. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_entry.c b/common/usbx_host_classes/src/ux_host_class_pima_entry.c new file mode 100644 index 0000000..909931a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_entry.c @@ -0,0 +1,122 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the pima class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* pima on the bus or when the USB pima is removed. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* command Pima class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_activate Activate pima class */ +/* _ux_host_class_pima_deactivate Deactivate pima class */ +/* */ +/* CALLED BY */ +/* */ +/* USBX stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) && + ((command -> ux_host_class_command_class == UX_HOST_CLASS_PIMA_CLASS) && + (command -> ux_host_class_command_subclass == UX_HOST_CLASS_PIMA_SUBCLASS) && + (command -> ux_host_class_command_protocol == UX_HOST_CLASS_PIMA_PROTOCOL))) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_pima_activate(command); + return(status); + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_pima_deactivate(command); + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_notification.c b/common/usbx_host_classes/src/ux_host_class_pima_notification.c new file mode 100644 index 0000000..e7d60a3 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_notification.c @@ -0,0 +1,217 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_notification PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the completion thread when a transfer */ +/* request has been completed either because the transfer is */ +/* successful or there was an error. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_short_get Get 16-bit value */ +/* _ux_utility_long_get Get 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* USBX stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_pima_notification(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_PIMA *pima; +UX_HOST_CLASS_PIMA_SESSION *pima_session; +UX_HOST_CLASS_PIMA_EVENT pima_event; + + /* Get the class instance for this transfer request. */ + pima = (UX_HOST_CLASS_PIMA *) transfer_request -> ux_transfer_request_class_instance; + + /* Check the state of the transfer. If there is an error, we do not proceed with this notification. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* We have an error. We do not rehook another transfer if the device instance is shutting down or + if the transfer was aborted by the class.. */ + if ((pima -> ux_host_class_pima_state == UX_HOST_CLASS_INSTANCE_SHUTDOWN) || + (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_ABORT)) + + /* We do not proceed. */ + return; + else + + { + + /* Reactivate the PIMA interrupt pipe. */ + _ux_host_stack_transfer_request(transfer_request); + + /* We do not proceed. */ + return; + } + + } + + /* Check if this packet is the first, if so we have the total length expected in the event. */ + if (pima -> ux_host_class_pima_event_buffer_current_length == 0) + { + + /* First packet. Maybe the only one needed. It may happen that the notification event is split amongst + several interrupt packets. */ + pima -> ux_host_class_pima_event_buffer_expected_length = _ux_utility_long_get(transfer_request -> ux_transfer_request_data_pointer + + UX_HOST_CLASS_PIMA_AEI_DATA_LENGTH); + + /* Set the current offset to the beginning of the buffer. */ + pima -> ux_host_class_pima_event_buffer_current_offset = pima -> ux_host_class_pima_event_buffer; + + } + + /* Check the length of this payload and make sure we have enough space. */ + if ((pima -> ux_host_class_pima_event_buffer_current_length + transfer_request -> ux_transfer_request_actual_length) <= + UX_HOST_CLASS_PIMA_AEI_MAX_LENGTH) + { + + /* We copy the current payload into our event notification buffer. */ + _ux_utility_memory_copy(pima -> ux_host_class_pima_event_buffer_current_offset, transfer_request -> ux_transfer_request_data_pointer, + transfer_request -> ux_transfer_request_actual_length); + + /* Set the new offset address. */ + pima -> ux_host_class_pima_event_buffer_current_offset += transfer_request -> ux_transfer_request_actual_length; + + /* Adjust the length. */ + pima -> ux_host_class_pima_event_buffer_current_length += transfer_request -> ux_transfer_request_actual_length; + } + else + + /* We come here when we have a buffer overflow. Do not proceed. */ + return; + + /* Check if we have a complete notification event. */ + if (pima -> ux_host_class_pima_event_buffer_current_length == pima -> ux_host_class_pima_event_buffer_expected_length) + { + + /* Save the current event in the pima instance. First, unpack the event code. */ + pima -> ux_host_class_pima_event_code = _ux_utility_short_get(pima -> ux_host_class_pima_event_buffer + UX_HOST_CLASS_PIMA_AEI_EVENT_CODE); + + /* Unpack the Transaction ID. */ + pima -> ux_host_class_pima_event_transaction_id = _ux_utility_long_get(pima -> ux_host_class_pima_event_buffer + UX_HOST_CLASS_PIMA_AEI_TRANSACTION_ID); + + /* Unpack the parameter 1. */ + pima -> ux_host_class_pima_event_parameter_1 = _ux_utility_long_get(pima -> ux_host_class_pima_event_buffer + UX_HOST_CLASS_PIMA_AEI_PARAMETER_1); + + /* Unpack the parameter 2. */ + pima -> ux_host_class_pima_event_parameter_2 = _ux_utility_long_get(pima -> ux_host_class_pima_event_buffer + UX_HOST_CLASS_PIMA_AEI_PARAMETER_2); + + /* Unpack the parameter 3. */ + pima -> ux_host_class_pima_event_parameter_3 = _ux_utility_long_get(pima -> ux_host_class_pima_event_buffer + UX_HOST_CLASS_PIMA_AEI_PARAMETER_3); + + /* Check if a session is valid. */ + if (pima -> ux_host_class_pima_session != UX_NULL) + { + + /* Get session pointer. */ + pima_session = pima -> ux_host_class_pima_session; + + /* Check if this session is valid or not. */ + if ((pima_session -> ux_host_class_pima_session_magic == UX_HOST_CLASS_PIMA_MAGIC_NUMBER) && + (pima_session -> ux_host_class_pima_session_state == UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED)) + { + + /* If the application demanded a callback when event occur, create a event notification + message. */ + if (pima_session -> ux_host_class_pima_session_event_callback != UX_NULL) + { + + /* Fill in the pima event structure. First with pima instance. */ + pima_event.ux_host_class_pima_event_pima_instance = pima; + + /* Fill in the opened session pointer. Since the pima class only supports + one session, this address is hardwired to the opened session and is not coming from + the event buffer. */ + pima_event.ux_host_class_pima_event_session = pima_session; + + /* Fill in all the event parameters in the event callback structure. */ + pima_event.ux_host_class_pima_event_code = pima -> ux_host_class_pima_event_code; + pima_event.ux_host_class_pima_event_transaction_id = pima -> ux_host_class_pima_event_transaction_id; + pima_event.ux_host_class_pima_event_parameter_1 = pima -> ux_host_class_pima_event_parameter_1; + pima_event.ux_host_class_pima_event_parameter_2 = pima -> ux_host_class_pima_event_parameter_2; + pima_event.ux_host_class_pima_event_parameter_3 = pima -> ux_host_class_pima_event_parameter_3; + + /* Send this event to the application. */ + pima_session -> ux_host_class_pima_session_event_callback(&pima_event); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_NOTIFICATION, pima, + pima -> ux_host_class_pima_event_code, + pima -> ux_host_class_pima_event_transaction_id, + pima -> ux_host_class_pima_event_parameter_1, + UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + } + } + } + + /* We will receive a complete new transaction. */ + pima -> ux_host_class_pima_event_buffer_current_length = 0; + } + /* Reactivate the PIMA interrupt pipe. */ + _ux_host_stack_transfer_request(transfer_request); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_num_objects_get.c b/common/usbx_host_classes/src/ux_host_class_pima_num_objects_get.c new file mode 100644 index 0000000..1131219 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_num_objects_get.c @@ -0,0 +1,120 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_num_object_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the number of objects for a specific storage. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_num_objects_get(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG storage_id, + ULONG object_format_code) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_NUM_OBJECTS_GET, pima, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Issue command to get the storage IDs. 2 parameter. */ + command.ux_host_class_pima_command_nb_parameters = 2; + + /* Parameter 1 is the Storage ID. */ + command.ux_host_class_pima_command_parameter_1 = storage_id; + + /* Parameter 2 is the Object Format Code. */ + command.ux_host_class_pima_command_parameter_2 = object_format_code; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_3 = 0; + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Then set the command to GET_NUM_OBJETCS. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_GET_NUM_OBJECTS; + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, 0 , UX_NULL, 0, 0); + + /* Check the result. If the result is OK, the parameter1 has the number of objects. */ + if (status == UX_SUCCESS) + + /* Store the number of objects into the current pima session. */ + pima_session -> ux_host_class_pima_session_nb_objects = command.ux_host_class_pima_command_parameter_1; + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_close.c b/common/usbx_host_classes/src/ux_host_class_pima_object_close.c new file mode 100644 index 0000000..d6843d7 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_close.c @@ -0,0 +1,219 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_object_close PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function closes an object, */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* object_handle The object handle */ +/* object Pointer to object info */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer */ +/* _ux_host_stack_endpoint_reset Reset endpoint */ +/* _ux_utility_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_object_close(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object) +{ + +UX_TRANSFER *transfer_request; +UCHAR *ptp_payload; +ULONG requested_length; +UINT status; + + UX_PARAMETER_NOT_USED(object_handle); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_OBJECT_CLOSE, pima, object, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if the object is already closed. */ + if (object -> ux_host_class_pima_object_state != UX_HOST_CLASS_PIMA_OBJECT_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_OBJECT_ALREADY_CLOSED ); + + /* Close the object. */ + object -> ux_host_class_pima_object_state = UX_HOST_CLASS_PIMA_OBJECT_STATE_CLOSED; + + /* If the transfer was not ended prematurely, we need to do the status phase. */ + if ( object -> ux_host_class_pima_object_transfer_status == UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_COMPLETED) + { + + /* The transfer for this transaction is now inactive. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_INACTIVE; + + /* Check if we had a ZLP condition during the data phase. */ + if (pima -> ux_host_class_pima_zlp_flag != UX_HOST_CLASS_PIMA_ZLP_NONE) + { + + /* We had a ZLP, so we now expect a zero length packet prior to the status phase. + We need to determine the direction. */ + if (pima -> ux_host_class_pima_zlp_flag == UX_HOST_CLASS_PIMA_ZLP_IN) + + /* We use the Bulk In pipe for receiving the zlp. */ + transfer_request = &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request; + + else + + /* We use the Bulk Out pipe for sending the zlp. */ + transfer_request = &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Initialize the payload to zero length. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + + /* Reset the ZLP now. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_NONE; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* There was an error, return to the caller. */ + return(status); + } + } + } + + /* We use the Bulk In pipe for receiving the response payload. */ + transfer_request = &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Get the pointer to the ptp payload. */ + ptp_payload = pima -> ux_host_class_pima_container ; + + /* Calculate the requested length for this payload. */ + requested_length = UX_HOST_CLASS_PIMA_RESPONSE_HEADER_SIZE; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = ptp_payload; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* There was an error, return to the caller. */ + return(status); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + } + + /* The transfer for this transaction is now inactive. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_INACTIVE; + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_copy.c b/common/usbx_host_classes/src/ux_host_class_pima_object_copy.c new file mode 100644 index 0000000..b97375f --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_copy.c @@ -0,0 +1,121 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_object_copy PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function copies one object from one location to another. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* object_handle Object handle to move */ +/* storage_id destination storage ID */ +/* parent_object_handle Parent object handle */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_object_copy(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle, + ULONG storage_id, + ULONG parent_object_handle) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_OBJECT_COPY, pima, object_handle, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Issue command to get the object info. 3 parameter. */ + command.ux_host_class_pima_command_nb_parameters = 3; + + /* Parameter 1 is the Object Handle. */ + command.ux_host_class_pima_command_parameter_1 = object_handle; + + /* Parameter 2 is the Storage ID. */ + command.ux_host_class_pima_command_parameter_2 = storage_id; + + /* Parameter 3 is the Parent Object ID. */ + command.ux_host_class_pima_command_parameter_3 = parent_object_handle; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Then set the command to COPY_OBJECT. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_COPY_OBJECT; + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, UX_HOST_CLASS_PIMA_DATA_PHASE_NONE , UX_NULL, + 0, 0); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_delete.c b/common/usbx_host_classes/src/ux_host_class_pima_object_delete.c new file mode 100644 index 0000000..e7341f3 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_delete.c @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_object_delete PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes an object. If the object handle is set to */ +/* 0xFFFFFFFF then all objects on the media are deleted. */ +/* */ +/* */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* object_handle The object handle */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_object_delete(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_OBJECT_DELETE, pima, object_handle, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Issue command to get the object info. 1 parameter. */ + command.ux_host_class_pima_command_nb_parameters = 1; + + /* Parameter 1 is the Object Handle. */ + command.ux_host_class_pima_command_parameter_1 = object_handle; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_2 = 0; + command.ux_host_class_pima_command_parameter_3 = 0; + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Then set the command to DELETE_OBJECT. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_DELETE_OBJECT; + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, UX_HOST_CLASS_PIMA_DATA_PHASE_NONE , UX_NULL, + 0, 0); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_get.c b/common/usbx_host_classes/src/ux_host_class_pima_object_get.c new file mode 100644 index 0000000..21c66cd --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_get.c @@ -0,0 +1,412 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_object_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets an object identified by the object_handle */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* object_handle The object handle */ +/* object Pointer to object info */ +/* object_buffer Buffer to be used */ +/* object_buffer_length Buffer length */ +/* object_actual_length Length read in that */ +/* command */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer */ +/* _ux_host_stack_endpoint_reset Reset endpoint */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_long_get Get 32-bit value */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_object_get(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object, + UCHAR *object_buffer, ULONG object_buffer_length, + ULONG *object_actual_length) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UX_TRANSFER *transfer_request; +UCHAR *ptp_payload; +ULONG requested_length; +ULONG total_length; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_OBJECT_GET, pima, object_handle, object, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if the object is already opened. */ + if (object -> ux_host_class_pima_object_state != UX_HOST_CLASS_PIMA_OBJECT_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_OBJECT_NOT_OPENED); + + /* Check the transfer status. If there was an error or transfer is completed, refuse transfer. */ + if ((object -> ux_host_class_pima_object_transfer_status == UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_COMPLETED) || + (object -> ux_host_class_pima_object_transfer_status == UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED)) + return (UX_HOST_CLASS_PIMA_RC_ACCESS_DENIED); + + /* Reset the actual length. */ + *object_actual_length = 0; + + /* This variable will remain untouched if the offset is not 0 and the requested length is 0. */ + status = UX_SUCCESS; + + /* Check if the offset to be read is at 0, if so, prepare the first read command. */ + if (object -> ux_host_class_pima_object_offset == 0) + { + + /* Set the object transfer status to active. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ACTIVE; + + /* Issue command to get the object info. 1 parameter. */ + command.ux_host_class_pima_command_nb_parameters = 1; + + /* Parameter 1 is the Object Handle. */ + command.ux_host_class_pima_command_parameter_1 = object_handle; + + /* Then set the command to GET_OBJECT. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_GET_OBJECT; + + /* We use the Bulk Out pipe for sending data out.. */ + transfer_request = &pima -> ux_host_class_pima_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Get the pointer to the ptp payload. */ + ptp_payload = pima -> ux_host_class_pima_container ; + + /* Calculate the requested length for this payload. */ + requested_length = UX_HOST_CLASS_PIMA_COMMAND_HEADER_SIZE + ((ULONG)sizeof(ULONG) * command.ux_host_class_pima_command_nb_parameters); + + /* Fill the command container. First the length of the total header and payload. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_LENGTH, requested_length); + + + /* Then the type of container : a command block here. */ + _ux_utility_short_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_TYPE, UX_HOST_CLASS_PIMA_CT_COMMAND_BLOCK); + + /* Now the command code to send. */ + _ux_utility_short_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_CODE, (USHORT)command.ux_host_class_pima_command_operation_code); + + /* Put the transaction ID. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_TRANSACTION_ID, + pima -> ux_host_class_pima_transaction_id++); + + /* Then fill in the parameters. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_1, + command.ux_host_class_pima_command_parameter_1); + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = ptp_payload; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* Set the object transfer status to aborted. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED; + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_ERROR); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Check for completion of transfer. If the transfer is partial, return to caller. + Partial transfer is not OK. */ + if (requested_length == transfer_request -> ux_transfer_request_actual_length) + { + + /* Obtain the first packet. This packet contains the header and some data. + We use the Bulk In pipe for receiving data .. */ + transfer_request = &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Get the pointer to the ptp payload. */ + ptp_payload = pima -> ux_host_class_pima_container ; + + /* Calculate the requested length for this payload. It is the minimum + of the application's requested length and the container size. */ + if (object_buffer_length < UX_HOST_CLASS_PIMA_CONTAINER_SIZE) + requested_length = object_buffer_length; + else + requested_length = UX_HOST_CLASS_PIMA_CONTAINER_SIZE; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = ptp_payload; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* Set the object transfer status to aborted. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED; + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_ERROR); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Ensure the transfer is larger than the header. */ + if (transfer_request -> ux_transfer_request_actual_length > UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE) + { + + /* We need to skip the header. Copying the necessary partial memory only. */ + _ux_utility_memory_copy(object_buffer, ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE, + transfer_request -> ux_transfer_request_actual_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE); + + /* Get the size of the entire data payload to be expected in this object transfer (data + header). If the size is on a boundary + the pima protocol demands that the last packet is a ZLP. */ + total_length = _ux_utility_long_get(ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_LENGTH); + + /* Check for remainder in last packet. */ + if ((total_length % pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_descriptor.wMaxPacketSize) == 0) + + /* We have a ZLP condition on a IN. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_IN; + else + + /* Do not expect a ZLP. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_NONE; + + /* Compute the total length of the data only. */ + total_length -= UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Check if the expected length remaining will be more than the current buffer. If so, we need to have a full payload + on a packet boundary. */ + if (total_length > object_buffer_length) + + /* Update what is left to be received. */ + object_buffer_length -= transfer_request -> ux_transfer_request_actual_length; + + else + + /* Update what is left to be received. */ + object_buffer_length -= transfer_request -> ux_transfer_request_actual_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Update the actual length. */ + *object_actual_length = transfer_request -> ux_transfer_request_actual_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Update where we will store the next data. */ + object_buffer += transfer_request -> ux_transfer_request_actual_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE; + + /* And the offset. */ + object -> ux_host_class_pima_object_offset += transfer_request -> ux_transfer_request_actual_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE; + } + else + { + + /* The transfer is smaller than the header, which is an error. */ + + /* Report error to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + + /* Return error. */ + return(UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + } + } + else + + /* We got a premature error. */ + return(UX_HOST_CLASS_PIMA_RC_INCOMPLETE_TRANSFER); + } + + /* We use the Bulk In pipe for receiving data .. */ + transfer_request = &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* We read a complete block. */ + while(object_buffer_length != 0) + { + + /* It may take several transactions. */ + if (object_buffer_length > UX_HOST_CLASS_PIMA_MAX_PAYLOAD) + + /* Set the requested length to the payload maximum. */ + requested_length = UX_HOST_CLASS_PIMA_MAX_PAYLOAD; + + else + + /* We can use the user supplied length to complete this request. */ + requested_length = object_buffer_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = object_buffer; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* Set the object transfer status to aborted. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED; + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_ERROR); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Update the object length expected by the user with what we actually received. */ + object_buffer_length -= transfer_request -> ux_transfer_request_actual_length; + + /* Update the actual length. */ + *object_actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* And the offset. */ + object -> ux_host_class_pima_object_offset += transfer_request -> ux_transfer_request_actual_length; + + /* And the object buffer pointer . */ + object_buffer += transfer_request -> ux_transfer_request_actual_length; + + /* Check to see if we are at the end of the object. */ + if (object -> ux_host_class_pima_object_offset == object -> ux_host_class_pima_object_compressed_size) + + /* The transfer for this transaction is completed. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_COMPLETED; + + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_handles_get.c b/common/usbx_host_classes/src/ux_host_class_pima_object_handles_get.c new file mode 100644 index 0000000..447a7dd --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_handles_get.c @@ -0,0 +1,176 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_storage_ids_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets a list if the current valid Storage IDS. There */ +/* is one Storage ID for each valid logical store. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* object_handles_array Pointer to store handles */ +/* object_handles_length Length of arrays */ +/* object_format_code Object Format Code */ +/* object_handle_association Object Handle */ +/* Association */ +/* */ +/* The 2 last parameter are optional and should be set to 0 if not */ +/* used. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* _ux_utility_long_get Get 32 bit value */ +/* _ux_utility_memory_allocate Allocate some memory */ +/* _ux_utility_memory_free Free some memory */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_object_handles_get(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG *object_handles_array, ULONG object_handles_length, + ULONG storage_id, ULONG object_format_code, ULONG object_handle_association) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UCHAR *object_handles_array_raw; +ULONG object_handle_length_raw; +ULONG count_object_handles; +ULONG nb_object_handles; +UINT status; + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check the number of handles and compare with the size of the array given by the user. */ + if ((pima_session -> ux_host_class_pima_session_nb_objects * sizeof(ULONG)) > object_handles_length) + return(UX_MEMORY_INSUFFICIENT); + + /* Issue command to get the storage IDs. 3 parameters. */ + command.ux_host_class_pima_command_nb_parameters = 3; + + /* Parameter 1 is the Storage ID. */ + command.ux_host_class_pima_command_parameter_1 = storage_id; + + /* Parameter 2 is optional. It is the Object Format Code. */ + command.ux_host_class_pima_command_parameter_2 = object_format_code; + + /* Parameter 3 is optional. It is the object handle association. */ + command.ux_host_class_pima_command_parameter_3 = object_handle_association; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Then set the command to GET_STORAGE_IDS. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_GET_OBJECT_HANDLES; + + /* Calculate the length the raw array. We multiply the number of handles by the size on the handle and + add a ULONG for the number of handles stored at the beginning of the array. */ + status = UX_SUCCESS; + object_handle_length_raw = 0; + UX_UTILITY_ADD_SAFE(pima_session -> ux_host_class_pima_session_nb_objects, 1, object_handle_length_raw, status); + if (status != UX_SUCCESS) + return(status); + UX_UTILITY_MULC_SAFE(object_handle_length_raw, (ULONG)sizeof(ULONG), object_handle_length_raw, status); + if (status != UX_SUCCESS) + return(status); + + /* Allocate some DMA safe memory for receiving the handles */ + object_handles_array_raw = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, object_handle_length_raw); + if (object_handles_array_raw == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, UX_HOST_CLASS_PIMA_DATA_PHASE_IN , object_handles_array_raw, + object_handle_length_raw, object_handle_length_raw); + + /* Check the result. If OK, the object handles array is returned properly. */ + if (status == UX_SUCCESS) + { + + /* Read the number of Object handles in the returned array. */ + nb_object_handles = _ux_utility_long_get(object_handles_array_raw); + + /* Save the number of object handles. */ + pima_session -> ux_host_class_pima_session_nb_objects = nb_object_handles; + + /* Check if the user gave us enough memory. */ + if ((nb_object_handles * sizeof(ULONG)) > object_handles_length) + + /* No, not enough memory to store the array. */ + return(UX_MEMORY_INSUFFICIENT); + + /* Unpack all object handles. */ + for(count_object_handles = 0; count_object_handles < nb_object_handles; count_object_handles++) + + /* Unpack one object handle at a time */ + *(object_handles_array + count_object_handles) = _ux_utility_long_get(object_handles_array_raw + sizeof(ULONG) + + (count_object_handles * sizeof(ULONG))); + } + + /* Free the original raw array. */ + _ux_utility_memory_free(object_handles_array_raw); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_info_get.c b/common/usbx_host_classes/src/ux_host_class_pima_object_info_get.c new file mode 100644 index 0000000..dc52b40 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_info_get.c @@ -0,0 +1,234 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_object_info_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the current object information block. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* object_handle The object handle */ +/* object Object structure to fill */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* _ux_utility_descriptor_parse Unpack descriptor */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_free Free allocated memory */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_object_info_get(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UCHAR *object_buffer; +UCHAR *object_pointer; +ULONG unicode_string_length; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_OBJECT_INFO_GET, pima, object_handle, object, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Issue command to get the object info. 1 parameter. */ + command.ux_host_class_pima_command_nb_parameters = 1; + + /* Parameter 1 is the Object Handle. */ + command.ux_host_class_pima_command_parameter_1 = object_handle; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_2 = 0; + command.ux_host_class_pima_command_parameter_3 = 0; + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Then set the command to GET_OBJECT_INFO. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_GET_OBJECT_INFO; + + /* Allocate some DMA safe memory for receiving the object info block. */ + object_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_OBJECT_MAX_LENGTH); + if (object == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, UX_HOST_CLASS_PIMA_DATA_PHASE_IN , object_buffer, + UX_HOST_CLASS_PIMA_OBJECT_MAX_LENGTH, UX_HOST_CLASS_PIMA_OBJECT_MAX_LENGTH); + + /* Check the result. If the result is OK, the object info block was read properly. */ + if (status == UX_SUCCESS) + { + /* Uncompress the object descriptor, at least the fixed part. */ + _ux_utility_descriptor_parse(object_buffer, + _ux_system_class_pima_object_structure, + UX_HOST_CLASS_PIMA_OBJECT_ENTRIES, + (UCHAR *) object); + + /* Copy the object filename field. Point to the beginning of the object description string. */ + object_pointer = object_buffer + UX_HOST_CLASS_PIMA_OBJECT_VARIABLE_OFFSET; + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object_pointer * 2) + 1; + + /* Check if string can fit in our buffer. */ + if (unicode_string_length > UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH) + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the object description field. */ + _ux_utility_memory_copy(object -> ux_host_class_pima_object_filename, object_pointer, unicode_string_length); + + /* Point to the next field. */ + object_pointer += unicode_string_length; + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object_pointer * 2) + 1; + + /* Ensure the string can fit in our buffer. */ + if (unicode_string_length > UX_HOST_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH) + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the capture date field. */ + _ux_utility_memory_copy(object -> ux_host_class_pima_object_capture_date, object_pointer, unicode_string_length); + + /* Point to the next field. */ + object_pointer += unicode_string_length; + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object_pointer * 2) + 1; + + /* Ensure the string can fit in our buffer. */ + if (unicode_string_length > UX_HOST_CLASS_PIMA_DATE_TIME_STRING_MAX_LENGTH) + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the modification date field. */ + _ux_utility_memory_copy(object -> ux_host_class_pima_object_modification_date, object_pointer, unicode_string_length); + + /* Point to the next field. */ + object_pointer += unicode_string_length; + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object_pointer * 2) + 1; + + /* Ensure the string can fit in our buffer. */ + if (unicode_string_length > UX_HOST_CLASS_PIMA_UNICODE_MAX_LENGTH) + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the keywords field. */ + _ux_utility_memory_copy(object -> ux_host_class_pima_object_keywords, object_pointer, unicode_string_length); + + /* Make the object closed. */ + object -> ux_host_class_pima_object_state = UX_HOST_CLASS_PIMA_OBJECT_STATE_CLOSED; + + /* Reset the reading\writing offset */ + object -> ux_host_class_pima_object_offset = 0; + } + else + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Report error to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + } + } + + /* Free the original object info buffer. */ + _ux_utility_memory_free(object_buffer); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_info_send.c b/common/usbx_host_classes/src/ux_host_class_pima_object_info_send.c new file mode 100644 index 0000000..863090a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_info_send.c @@ -0,0 +1,252 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_object_info_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends an object information block prior to sending */ +/* a new object. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* storage_id StorageID where to store */ +/* parent_object_id Parent object id */ +/* object Object info structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_free Free allocated memory */ +/* _ux_utility_descriptor_pack Pack descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_object_info_send(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG storage_id, + ULONG parent_object_id, + UX_HOST_CLASS_PIMA_OBJECT *object) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UCHAR *object_buffer; +UCHAR *object_buffer_end; +UCHAR *object_pointer; +ULONG unicode_string_length; +ULONG object_info_length; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_OBJECT_INFO_SEND, pima, object, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Issue command to set the object info. 2 parameter. */ + command.ux_host_class_pima_command_nb_parameters = 2; + + /* Parameter 1 is the Storage ID. */ + command.ux_host_class_pima_command_parameter_1 = storage_id; + + /* Parameter 2 is the Parent Object ID. */ + command.ux_host_class_pima_command_parameter_2 = parent_object_id; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_3 = 0; + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Then set the command to SEND_OBJECT_INFO. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_SEND_OBJECT_INFO; + + /* Allocate some DMA safe memory for sending the object info block. */ + object_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_OBJECT_MAX_LENGTH); + if (object == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Get the end of the object buffer. */ + object_buffer_end = object_buffer + UX_HOST_CLASS_PIMA_OBJECT_MAX_LENGTH; + + /* The object info structure coming from the application needs to be packed. */ + _ux_utility_descriptor_pack((UCHAR *) object, + _ux_system_class_pima_object_structure, + UX_HOST_CLASS_PIMA_OBJECT_ENTRIES, + object_buffer); + + /* Copy the object filename field. Point to the beginning of the object description string. */ + object_pointer = object_buffer + UX_HOST_CLASS_PIMA_OBJECT_VARIABLE_OFFSET; + + /* Get the unicode string length for the filename. */ + unicode_string_length = ((ULONG) *object -> ux_host_class_pima_object_filename * 2) + 1; + + /* Is there enough room for this string? */ + if (object_pointer + unicode_string_length > object_buffer_end) + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + + else + + /* Continue. */ + status = UX_SUCCESS; + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the object description field. */ + _ux_utility_memory_copy(object_pointer, object -> ux_host_class_pima_object_filename, unicode_string_length); + + /* Point to the next field. */ + object_pointer += unicode_string_length; + + /* Get the unicode string length of the capture date. */ + unicode_string_length = ((ULONG) *object -> ux_host_class_pima_object_capture_date * 2) + 1; + + /* Is there enough room for this string? */ + if (object_pointer + unicode_string_length > object_buffer_end) + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the capture date field. */ + _ux_utility_memory_copy(object_pointer, object -> ux_host_class_pima_object_capture_date, unicode_string_length); + + /* Point to the next field. */ + object_pointer += unicode_string_length; + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object -> ux_host_class_pima_object_modification_date * 2) + 1; + + /* Is there enough room for this string? */ + if (object_pointer + unicode_string_length > object_buffer_end) + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the modification date field. */ + _ux_utility_memory_copy(object_pointer, object -> ux_host_class_pima_object_modification_date, unicode_string_length); + + /* Point to the next field. */ + object_pointer += unicode_string_length; + + /* Get the unicode string length. */ + unicode_string_length = ((ULONG) *object -> ux_host_class_pima_object_keywords * 2) + 1; + + /* Is there enough room for this string? */ + if (object_pointer + unicode_string_length > object_buffer_end) + + /* Return error. */ + status = UX_MEMORY_INSUFFICIENT; + } + + /* Is there enough space? */ + if (status == UX_SUCCESS) + { + + /* Copy that string into the keywords field. */ + _ux_utility_memory_copy(object_pointer, object -> ux_host_class_pima_object_keywords, unicode_string_length); + + /* Point to the next field. */ + object_pointer += unicode_string_length; + + /* Calculate the length of the payload. */ + object_info_length = (ULONG ) (object_pointer - object_buffer); + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, UX_HOST_CLASS_PIMA_DATA_PHASE_OUT , object_buffer, + object_info_length, object_info_length); + + /* If the status is OK, the device sent us the Object handle in the response. */ + if (status == UX_SUCCESS) + + /* Update the object handle. */ + object -> ux_host_class_pima_object_handle_id = command.ux_host_class_pima_command_parameter_2; + } + else + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_MEMORY_INSUFFICIENT, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Report error to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + } + + /* Free the original object info buffer. */ + _ux_utility_memory_free(object_buffer); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_move.c b/common/usbx_host_classes/src/ux_host_class_pima_object_move.c new file mode 100644 index 0000000..46768a2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_move.c @@ -0,0 +1,121 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_object_move PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function moves an object from one location to another. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* object_handle Object handle to move */ +/* storage_id destination storage ID */ +/* parent_object_handle Parent object handle */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_object_move(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle, + ULONG storage_id, + ULONG parent_object_handle) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_OBJECT_MOVE, pima, object_handle, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Issue command to get the object info. 3 parameter. */ + command.ux_host_class_pima_command_nb_parameters = 3; + + /* Parameter 1 is the Object Handle. */ + command.ux_host_class_pima_command_parameter_1 = object_handle; + + /* Parameter 2 is the Storage ID. */ + command.ux_host_class_pima_command_parameter_2 = storage_id; + + /* Parameter 3 is the Parent Object ID. */ + command.ux_host_class_pima_command_parameter_3 = parent_object_handle; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Then set the command to MOVE_OBJECT. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_MOVE_OBJECT; + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, UX_HOST_CLASS_PIMA_DATA_PHASE_NONE , UX_NULL, + 0, 0); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_open.c b/common/usbx_host_classes/src/ux_host_class_pima_object_open.c new file mode 100644 index 0000000..b8e0569 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_open.c @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_object_open PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function opens an object for a read or write operation */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* object_handle The object handle */ +/* object Pointer to object info */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_object_open(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object) +{ + + UX_PARAMETER_NOT_USED(object_handle); + UX_PARAMETER_NOT_USED(pima); + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if the object is already opened. */ + if (object -> ux_host_class_pima_object_state != UX_HOST_CLASS_PIMA_OBJECT_STATE_CLOSED) + return (UX_HOST_CLASS_PIMA_RC_OBJECT_ALREADY_OPENED); + + /* Open the object. */ + object -> ux_host_class_pima_object_state = UX_HOST_CLASS_PIMA_OBJECT_STATE_OPENED; + + /* Reset the object offset. */ + object -> ux_host_class_pima_object_offset = 0; + + /* Set the object transfer status to inactive. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_INACTIVE; + + /* Return completion status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_send.c b/common/usbx_host_classes/src/ux_host_class_pima_object_send.c new file mode 100644 index 0000000..a2cf18c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_send.c @@ -0,0 +1,376 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_object_send PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends an object to the media. This commands should be */ +/* be proceeded by a object_info_send command. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* object Pointer to object info */ +/* object_buffer Buffer to be used */ +/* object_buffer_length Buffer length */ +/* callback_function Application function to */ +/* callback when buffer */ +/* needs to be written */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer */ +/* _ux_host_stack_endpoint_reset Reset endpoint */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_short_put Put 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_object_send(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + UX_HOST_CLASS_PIMA_OBJECT *object, + UCHAR *object_buffer, ULONG object_buffer_length) +{ + + +UX_HOST_CLASS_PIMA_COMMAND command; +UX_TRANSFER *transfer_request; +UCHAR *ptp_payload; +ULONG requested_length; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_OBJECT_SEND, pima, object, object_buffer, object_buffer_length, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if the object is already opened. */ + if (object -> ux_host_class_pima_object_state != UX_HOST_CLASS_PIMA_OBJECT_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_OBJECT_NOT_OPENED); + + /* Check the transfer status. If there was an error or transfer is completed, refuse transfer. */ + if ((object -> ux_host_class_pima_object_transfer_status == UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_COMPLETED) || + (object -> ux_host_class_pima_object_transfer_status == UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED)) + return (UX_HOST_CLASS_PIMA_RC_ACCESS_DENIED); + + /* This variable will remain untouched if the offset is not 0 and the requested length is 0. */ + status = UX_SUCCESS; + + /* Check if the offset to be read is at 0, if so, prepare the first write command. */ + if (object -> ux_host_class_pima_object_offset == 0) + { + + /* Set the object transfer status to active. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ACTIVE; + + /* Issue command to get the object info. no parameter. */ + command.ux_host_class_pima_command_nb_parameters = 0; + + /* Then set the command to SEND_OBJECT. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_SEND_OBJECT; + + /* We use the Bulk Out pipe for sending command out.. */ + transfer_request = &pima -> ux_host_class_pima_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Get the pointer to the ptp payload. */ + ptp_payload = pima -> ux_host_class_pima_container ; + + /* Calculate the requested length for this payload. */ + requested_length = UX_HOST_CLASS_PIMA_COMMAND_HEADER_SIZE + ((ULONG)sizeof(ULONG) * command.ux_host_class_pima_command_nb_parameters); + + /* Fill the command container. First the length of the total header and payload. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_LENGTH, requested_length); + + /* Then the type of container : a command block here. */ + _ux_utility_short_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_TYPE, UX_HOST_CLASS_PIMA_CT_COMMAND_BLOCK); + + /* Now the command code to send. */ + _ux_utility_short_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_CODE, (USHORT)command.ux_host_class_pima_command_operation_code); + + /* Put the transaction ID. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_TRANSACTION_ID, + pima -> ux_host_class_pima_transaction_id++); + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = ptp_payload; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* Set the object transfer status to aborted. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED; + + /* There was an error, return to the caller. */ + return(status); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Check for completion of transfer. If the transfer is partial, return to caller. + Partial transfer is not OK. */ + if (requested_length == transfer_request -> ux_transfer_request_actual_length) + { + + /* Send the first packet. This packet contains the header and some data. + We use the Bulk Out pipe for sending data .. */ + transfer_request = &pima -> ux_host_class_pima_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Get the pointer to the ptp payload. */ + ptp_payload = pima -> ux_host_class_pima_container ; + + /* Container type is a data type. */ + *(ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_TYPE) = UX_HOST_CLASS_PIMA_CT_DATA_BLOCK; + + /* Fill in the header values. Start with the length of the container. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_LENGTH, + object -> ux_host_class_pima_object_compressed_size + UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE); + + /* If the total payload is on a boundary, we need a ZLP to mark the end. */ + if (((object -> ux_host_class_pima_object_compressed_size + UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE) % + pima -> ux_host_class_pima_bulk_out_endpoint-> ux_endpoint_descriptor.wMaxPacketSize) == 0) + + /* We have a ZLP condition. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_OUT; + else + + /* Do not expect a ZLP. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_NONE; + + /* Calculate the requested length for this payload. */ + requested_length = UX_HOST_CLASS_PIMA_CONTAINER_SIZE; + + /* Check to see if we have enough to fill the first packet. */ + if (requested_length > (UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE + object_buffer_length)) + + /* This is a small object, enough to fit into the fist packet. */ + requested_length = UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE + object_buffer_length; + + /* We need to skip the header. Copying the necessary partial memory only. */ + _ux_utility_memory_copy(ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE, object_buffer, + requested_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE); + + /* Update the offset. */ + object -> ux_host_class_pima_object_offset += requested_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE; + + /* And the current object buffer pointer. */ + object_buffer += requested_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Adjust the remaining buffer length. */ + object_buffer_length -= requested_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = ptp_payload; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* Set the object transfer status to aborted. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED; + + /* There was an error, return to the caller. */ + return(status); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + + } + else + + /* We got a premature error. */ + return(UX_HOST_CLASS_PIMA_RC_INCOMPLETE_TRANSFER); + } + + + /* We use the Bulk Out pipe for sending data .. */ + transfer_request = &pima -> ux_host_class_pima_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* We send a complete block. */ + while(object_buffer_length != 0) + { + + /* It may take several transactions. */ + if (object_buffer_length > UX_HOST_CLASS_PIMA_MAX_PAYLOAD) + + /* Set the requested length to the payload maximum. */ + requested_length = UX_HOST_CLASS_PIMA_MAX_PAYLOAD; + + else + + /* We can use the user supplied length to complete this request. */ + requested_length = object_buffer_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = object_buffer; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* Set the object transfer status to aborted. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED; + + /* There was an error, return to the caller. */ + return(status); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Update the object length expected by the user with what we actually sent. */ + object_buffer_length -= transfer_request -> ux_transfer_request_actual_length; + + /* And the offset. */ + object -> ux_host_class_pima_object_offset += transfer_request -> ux_transfer_request_actual_length; + + /* And the object buffer pointer . */ + object_buffer += transfer_request -> ux_transfer_request_actual_length; + + /* Check to see if we are at the end of the object. */ + if (object -> ux_host_class_pima_object_offset == object -> ux_host_class_pima_object_compressed_size) + + /* The transfer for this transaction is completed. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_COMPLETED; + + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_object_transfer_abort.c b/common/usbx_host_classes/src/ux_host_class_pima_object_transfer_abort.c new file mode 100644 index 0000000..1663b0d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_object_transfer_abort.c @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_object_transfer_abort PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function aborts a pending transfer to\from an object. */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* object_handle The object handle */ +/* object Pointer to object info */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_request_cancel Cancel request */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_object_transfer_abort(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object) +{ + +UINT status; + + UX_PARAMETER_NOT_USED(object_handle); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_OBJECT_TRANSFER_ABORT, pima, object_handle, object, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if the object is already closed. */ + if (object -> ux_host_class_pima_object_state != UX_HOST_CLASS_PIMA_OBJECT_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_OBJECT_ALREADY_CLOSED ); + + /* Cancel the current request. */ + status = _ux_host_class_pima_request_cancel(pima); + + /* The transfer for this transaction was aborted. No need to issue a status phase when the object is closed. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED; + + /* Reset the potential ZLP condition. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_NONE; + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_read.c b/common/usbx_host_classes/src/ux_host_class_pima_read.c new file mode 100644 index 0000000..d775fcd --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_read.c @@ -0,0 +1,287 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads a data payload from the Pima device. This */ +/* function first read a header followed by some data. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* data_pointer Pointer to data to read */ +/* data_length Length of data to read */ +/* callback_function Application function to call */ +/* to get the rest of the data */ +/* max_payload_data Maximum data received in one */ +/* data payload. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_host_stack_endpoint_reset Reset endpoint */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_long_get Get a long 32 bit value */ +/* _ux_utility_short_get Get a short 16 bit value */ +/* _ux_utility_memory_copy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_read(UX_HOST_CLASS_PIMA *pima, UCHAR *data_pointer, + ULONG data_length, + ULONG max_payload_length) + +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG header_length; +UCHAR *ptp_payload; +ULONG requested_length; +ULONG payload_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_READ, pima, data_pointer, data_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We use the Bulk In pipe for receiving data .. */ + transfer_request = &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Get the pointer to the ptp payload. */ + ptp_payload = pima -> ux_host_class_pima_container ; + + /* Calculate the requested length for this payload. */ + requested_length = UX_HOST_CLASS_PIMA_CONTAINER_SIZE; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = ptp_payload; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* There was an error, return to the caller. */ + return(status); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Ensure the transfer is greater than the size of a PIMA header. */ + if (transfer_request -> ux_transfer_request_actual_length <= UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE) + + /* We have a malformed packet. Return error. */ + return(UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + + /* Get the expected length from the header. */ + header_length = _ux_utility_long_get(ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_LENGTH); + + /* Check for remainder in last packet. */ + if ((header_length % pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_descriptor.wMaxPacketSize) == 0) + + /* We have a ZLP condition on a IN. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_IN; + else + + /* Do not expect a ZLP. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_NONE; + + /* The length returned should be smaller than the length requested. */ + if ((header_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE)> data_length) + return(UX_ERROR); + + /* We may have had data in the first packet, if so adjust the data_length. */ + data_length = header_length - transfer_request -> ux_transfer_request_actual_length; + + /* Copying the necessary partial memory. */ + _ux_utility_memory_copy(data_pointer, ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE, + transfer_request -> ux_transfer_request_actual_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE); + + /* Adjust the data payload pointer. */ + data_pointer += (transfer_request -> ux_transfer_request_actual_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE); + + /* Now we can read the data from the device. */ + while(data_length) + { + + /* Check if need to split the data payload into smaller packets. */ + if (data_length > max_payload_length) + + /* We cannot send everything in this payload. */ + payload_length = max_payload_length; + else + + /* Either this is the last packet or we we have a small packet to send. */ + payload_length = data_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = payload_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* There was an error, return to the caller. */ + return(status); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Check for completion of transfer. If the transfer is partial, return to caller. + Partial transfer is not OK. */ + if (payload_length != transfer_request -> ux_transfer_request_actual_length) + return(UX_TRANSFER_ERROR); + + /* Adjust the total length to transfer. */ + data_length -= payload_length; + + /* Adjust the data pointer. */ + data_pointer += payload_length; + + } + + /* If we have a ZLP condition, read from the device one more time with a zero packet. */ + if (pima -> ux_host_class_pima_zlp_flag == UX_HOST_CLASS_PIMA_ZLP_IN) + { + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* There was an error, return to the caller. */ + return(status); + } + + /* Reset the ZLP. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_NONE; + } + } + + /* We have finished receiving the data. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_request_cancel.c b/common/usbx_host_classes/src/ux_host_class_pima_request_cancel.c new file mode 100644 index 0000000..892ca76 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_request_cancel.c @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_request_cancel PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cancels a request. */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_short_put Put 16-bit value */ +/* _ux_utility_short_get Get 16-bit value */ +/* _ux_utility_long_put Put 32-bit value */ +/* _ux_utility_delay_ms Delay ms */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_request_cancel(UX_HOST_CLASS_PIMA *pima) +{ + +UX_TRANSFER *transfer_request; +UX_ENDPOINT *control_endpoint; +UCHAR *request_payload; +UINT status; +UINT device_status; +ULONG payload_length; +ULONG command_retry_counter; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_REQUEST_CANCEL, pima, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Allocate some DMA safe memory for the command data payload. We use mode than needed because + we use this buffer for both the command and the status phase. */ + request_payload = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_REQUEST_STATUS_DATA_LENGTH); + if (request_payload == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Fill in the payload buffer with cancellation code. */ + _ux_utility_short_put(request_payload + UX_HOST_CLASS_PIMA_REQUEST_CANCEL_OFFSET_CODE, + UX_HOST_CLASS_PIMA_REQUEST_CANCEL_CODE ); + + /* Fill in the payload buffer with transactionID. */ + _ux_utility_long_put(request_payload + UX_HOST_CLASS_PIMA_REQUEST_CANCEL_OFFSET_TRANSACTION_ID, + pima -> ux_host_class_pima_transaction_id++); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &pima -> ux_host_class_pima_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Create a transfer_request for the CANCEL request. */ + transfer_request -> ux_transfer_request_data_pointer = request_payload; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_PIMA_REQUEST_CANCEL_DATA_LENGTH; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PIMA_REQUEST_CANCEL_COMMAND; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check if status is OK. If the command did not work, we have a major problem. */ + if(status == UX_SUCCESS) + { + + /* Initialize the command retry counter. */ + command_retry_counter = UX_HOST_CLASS_PIMA_REQUEST_STATUS_COMMAND_COUNTER; + + /* This command may be retried a few times. */ + while (command_retry_counter-- != 0) + { + + /* We need to wait for the device to be OK. For that we issue a GET_DEVICE_STATUS command. */ + transfer_request -> ux_transfer_request_data_pointer = request_payload; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_PIMA_REQUEST_CANCEL_DATA_LENGTH; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PIMA_REQUEST_STATUS_COMMAND; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, abort if there is an error. */ + if (status != UX_SUCCESS) + break; + + /* Extract the payload length from the status buffer. */ + payload_length = _ux_utility_short_get(request_payload + UX_HOST_CLASS_PIMA_REQUEST_STATUS_OFFSET_LENGTH); + + /* Check the data payload length. */ + if (payload_length < UX_HOST_CLASS_PIMA_REQUEST_STATUS_OFFSET_CODE + sizeof(UINT)) + { + + /* We have a data format error. */ + status = UX_ERROR; + break; + } + + /* Extract the device status. */ + device_status = _ux_utility_short_get(request_payload + UX_HOST_CLASS_PIMA_REQUEST_STATUS_OFFSET_CODE); + + /* If the device status is OK, we have a successful cancellation. */ + if (device_status == UX_HOST_CLASS_PIMA_RC_OK) + { + + /* Status is OK. exit the command loop. */ + status = UX_SUCCESS; + break; + } + else + { + /* Force the status to error. */ + status = UX_ERROR; + + + /* We should wait a little bit before re-issuing the command. */ + _ux_utility_delay_ms(UX_HOST_CLASS_PIMA_REQUEST_STATUS_COMMAND_DELAY); + + } + } + + } + + /* Free allocated resources. */ + _ux_utility_memory_free(request_payload); + + /* Return completion status. */ + return(status); + +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_session_close.c b/common/usbx_host_classes/src/ux_host_class_pima_session_close.c new file mode 100644 index 0000000..8f8ed6a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_session_close.c @@ -0,0 +1,123 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_session_close PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function closes a session with the PIMA device. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_session_close(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_SESSION_CLOSE, pima, pima_session, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* The transaction ID in the PIMA instance should be reset. */ + pima -> ux_host_class_pima_transaction_id = 0; + + /* Issue command to close the session with the PIMA device. No parameter. */ + command.ux_host_class_pima_command_nb_parameters = 0; + + /* Then set the command to CLOSE_SESSION. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_CLOSE_SESSION; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_1 = 0; + command.ux_host_class_pima_command_parameter_2 = 0; + command.ux_host_class_pima_command_parameter_3 = 0; + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, 0 , UX_NULL, 0, 0); + + /* Check the result. If OK, the session was closed properly. */ + if (status == UX_SUCCESS) + { + + /* Reset the PIMA session in the pima instance. */ + pima -> ux_host_class_pima_session = UX_NULL; + + /* Reset the magic field. */ + pima_session -> ux_host_class_pima_session_magic = 0; + + /* Mark the session as closed. */ + pima_session -> ux_host_class_pima_session_state = UX_HOST_CLASS_PIMA_SESSION_STATE_CLOSED; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_session_open.c b/common/usbx_host_classes/src/ux_host_class_pima_session_open.c new file mode 100644 index 0000000..e72a481 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_session_open.c @@ -0,0 +1,128 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_session_open PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function opens a session with the PIMA device. The session */ +/* is maintained in this state until the session is closed or the */ +/* device is unmounted. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_session_open(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +ULONG status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_SESSION_OPEN, pima, pima_session, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if there is already a session opened. */ + if (pima -> ux_host_class_pima_session != UX_NULL) + return (UX_HOST_CLASS_PIMA_RC_SESSION_ALREADY_OPENED); + + /* The transaction ID in the PIMA instance should be reset. */ + pima -> ux_host_class_pima_transaction_id = 0; + + /* Issue command to open the session with the PIMA device. First set the number of parameters. */ + command.ux_host_class_pima_command_nb_parameters = 1; + + /* Then set the command to OPEN_SESSION. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_OPEN_SESSION; + + /* The session ID is the handle to the session. */ + command.ux_host_class_pima_command_parameter_1 = (ULONG) (ALIGN_TYPE) pima_session; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_2 = 0; + command.ux_host_class_pima_command_parameter_3 = 0; + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, 0 , UX_NULL, 0, 0); + + /* Check the result. If OK, the session was opened properly. */ + if (status == UX_SUCCESS) + { + + /* Store the session pointer in the PIMA instance. The PIMA class instance + only supports one opened session at a time at this stage. */ + pima -> ux_host_class_pima_session = pima_session; + + /* Save the session ID in the session container. This is not too useful since + the session ID is the session structure address. */ + pima_session -> ux_host_class_pima_session_id = (ALIGN_TYPE) pima_session; + + /* Put the magic number in the session instance. */ + pima_session -> ux_host_class_pima_session_magic = UX_HOST_CLASS_PIMA_MAGIC_NUMBER; + + /* Mark the session as opened. */ + pima_session -> ux_host_class_pima_session_state = UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_storage_ids_get.c b/common/usbx_host_classes/src/ux_host_class_pima_storage_ids_get.c new file mode 100644 index 0000000..ace2003 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_storage_ids_get.c @@ -0,0 +1,158 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + +UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH_ASSERT + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_storage_ids_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets a list if the current valid Storage IDS. There */ +/* is one Storage ID for each valid logical store. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_long_get Get 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_storage_ids_get(UX_HOST_CLASS_PIMA *pima, UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG *storage_ids_array, ULONG storage_id_length) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UINT status; +UCHAR *storage_ids; +ULONG count_storage_ids; +ULONG nb_storage_ids; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_STORAGE_IDS_GET, pima, storage_ids_array, storage_id_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Issue command to get the storage IDs. No parameter. */ + command.ux_host_class_pima_command_nb_parameters = 0; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_1 = 0; + command.ux_host_class_pima_command_parameter_2 = 0; + command.ux_host_class_pima_command_parameter_3 = 0; + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Then set the command to GET_STORAGE_IDS. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_GET_STORAGE_IDS; + + /* Allocate some DMA safe memory for receiving the IDs. + * UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH_ASSERT checks if calculation of + * UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH is OK. + */ + storage_ids = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH); + if (storage_ids == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, UX_HOST_CLASS_PIMA_DATA_PHASE_IN , storage_ids, + UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH, UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH); + + /* Check the result. If OK, the storage ID array is returned properly. */ + if (status == UX_SUCCESS) + { + + /* Read the number of Storage IDs in the returned array. */ + nb_storage_ids = _ux_utility_long_get(storage_ids); + + /* Ensure we do read the array beyond the allocated memory. */ + if (((nb_storage_ids + 1) * sizeof(ULONG)) > UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH) + + /* If we get here we should probably increase the value for UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH */ + nb_storage_ids = (UX_HOST_CLASS_PIMA_STORAGE_IDS_LENGTH / sizeof(ULONG)) - 1; + + /* Save the number of storage IDs. */ + pima_session -> ux_host_class_pima_session_nb_storage_ids = nb_storage_ids; + + /* Check if the user gave us enough memory. */ + if ((nb_storage_ids * sizeof(ULONG)) > storage_id_length) + + /* No, not enough memory to store the array. */ + return(UX_MEMORY_INSUFFICIENT); + + /* Unpack all storage IDS. */ + for(count_storage_ids = 0; count_storage_ids < nb_storage_ids; count_storage_ids++) + + /* Unpack one ID at a time */ + *(storage_ids_array + count_storage_ids) = _ux_utility_long_get(storage_ids + sizeof(ULONG) + + (count_storage_ids * sizeof(ULONG))); + } + + /* Free the original storage ID buffer. */ + _ux_utility_memory_free(storage_ids); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_storage_info_get.c b/common/usbx_host_classes/src/ux_host_class_pima_storage_info_get.c new file mode 100644 index 0000000..3f60e0a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_storage_info_get.c @@ -0,0 +1,157 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_storage_info_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the current storage information block. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* storage_id The storage ID */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_pima_command Pima command function */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_memory_free Free memory */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_storage_info_get(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG storage_id, UX_HOST_CLASS_PIMA_STORAGE *storage) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UINT status; +UCHAR *storage_buffer; +UCHAR *storage_pointer; +ULONG unicode_string_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_STORAGE_INFO_GET, pima, storage_id, storage, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Issue command to get the storage IDs. 1 parameter. */ + command.ux_host_class_pima_command_nb_parameters = 1; + + /* Parameter 1 is the Storage ID. */ + command.ux_host_class_pima_command_parameter_1 = storage_id; + + /* Other parameters unused. */ + command.ux_host_class_pima_command_parameter_2 = 0; + command.ux_host_class_pima_command_parameter_3 = 0; + command.ux_host_class_pima_command_parameter_4 = 0; + command.ux_host_class_pima_command_parameter_5 = 0; + + /* Then set the command to GET_STORAGE_INFO. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_GET_STORAGE_INFO; + + /* Allocate some DMA safe memory for receiving the storage info block. */ + storage_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PIMA_STORAGE_MAX_LENGTH); + if (storage == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Issue the command. */ + status = _ux_host_class_pima_command(pima, &command, UX_HOST_CLASS_PIMA_DATA_PHASE_IN , storage_buffer, + UX_HOST_CLASS_PIMA_STORAGE_MAX_LENGTH, UX_HOST_CLASS_PIMA_STORAGE_MAX_LENGTH); + + /* Check the result. If the result is OK, the storage info block was read properly. */ + if (status == UX_SUCCESS) + { + /* Uncompress the storage descriptor, at least the fixed part. */ + _ux_utility_descriptor_parse(storage_buffer, + _ux_system_class_pima_object_structure, + UX_HOST_CLASS_PIMA_OBJECT_ENTRIES, + (UCHAR *) storage); + + /* Copy the storage description field. Point to the beginning of the storage description string. */ + storage_pointer = storage_buffer + UX_HOST_CLASS_PIMA_STORAGE_VARIABLE_OFFSET; + + /* Get the unicode string length. */ + unicode_string_length = (ULONG) *storage_pointer ; + + /* Copy that string into the storage description field. */ + _ux_utility_memory_copy(storage -> ux_host_class_pima_storage_description, storage_pointer, unicode_string_length); + + /* Point to the volume label. */ + storage_pointer = storage_buffer + UX_HOST_CLASS_PIMA_STORAGE_VARIABLE_OFFSET + unicode_string_length; + + /* Get the unicode string length. */ + unicode_string_length = (ULONG) *storage_pointer ; + + /* Copy that string into the storage volume label field. */ + _ux_utility_memory_copy(storage -> ux_host_class_pima_storage_description, storage_pointer, unicode_string_length); + + } + + /* Free the original storage info buffer. */ + _ux_utility_memory_free(storage_buffer); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_thumb_get.c b/common/usbx_host_classes/src/ux_host_class_pima_thumb_get.c new file mode 100644 index 0000000..457aa87 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_thumb_get.c @@ -0,0 +1,372 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PIMA Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_thumb_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets a thumb image identified by the object_handle */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* pima_session Pointer to pima session */ +/* object_handle The object handle */ +/* object Pointer to object info */ +/* thumb_buffer Buffer to be used */ +/* thumb_buffer_length Buffer length */ +/* thumb_actual_length Length read in that */ +/* command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_host_stack_endpoint_reset Reset endpoint */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_short_put Put 16-bit value */ +/* _ux_utility_long_put Put 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* USB application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_thumb_get(UX_HOST_CLASS_PIMA *pima, + UX_HOST_CLASS_PIMA_SESSION *pima_session, + ULONG object_handle, UX_HOST_CLASS_PIMA_OBJECT *object, + UCHAR *thumb_buffer, ULONG thumb_buffer_length, + ULONG *thumb_actual_length) +{ + +UX_HOST_CLASS_PIMA_COMMAND command; +UX_TRANSFER *transfer_request; +UCHAR *ptp_payload; +ULONG requested_length; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_THUMB_GET, pima, object_handle, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Check if this session is valid or not. */ + if (pima_session -> ux_host_class_pima_session_magic != UX_HOST_CLASS_PIMA_MAGIC_NUMBER) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if this session is opened or not. */ + if (pima_session -> ux_host_class_pima_session_state != UX_HOST_CLASS_PIMA_SESSION_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_SESSION_NOT_OPEN); + + /* Check if the object is already opened. */ + if (object -> ux_host_class_pima_object_state != UX_HOST_CLASS_PIMA_OBJECT_STATE_OPENED) + return (UX_HOST_CLASS_PIMA_RC_OBJECT_NOT_OPENED); + + /* Check the transfer status. If there was an error or transfer is completed, refuse transfer. */ + if ((object -> ux_host_class_pima_object_transfer_status == UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_COMPLETED) || + (object -> ux_host_class_pima_object_transfer_status == UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED)) + return (UX_HOST_CLASS_PIMA_RC_ACCESS_DENIED); + + + /* Reset the actual length. */ + *thumb_actual_length = 0; + + /* This variable will remain untouched if the offset is not 0 and the requested length is 0. */ + status = UX_SUCCESS; + + /* Check if the offset to be read is at 0, if so, prepare the first read command. */ + if (object -> ux_host_class_pima_object_offset == 0) + { + + /* Set the object transfer status to active. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ACTIVE; + + /* Issue command to get the object info. 1 parameter. */ + command.ux_host_class_pima_command_nb_parameters = 1; + + /* Parameter 1 is the Object Handle. */ + command.ux_host_class_pima_command_parameter_1 = object_handle; + + /* Then set the command to GET_OBJECT. */ + command.ux_host_class_pima_command_operation_code = UX_HOST_CLASS_PIMA_OC_GET_THUMB; + + /* We use the Bulk Out pipe for sending data out.. */ + transfer_request = &pima -> ux_host_class_pima_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Get the pointer to the ptp payload. */ + ptp_payload = pima -> ux_host_class_pima_container ; + + /* Calculate the requested length for this payload. */ + requested_length = UX_HOST_CLASS_PIMA_COMMAND_HEADER_SIZE + ((ULONG)sizeof(ULONG) * command.ux_host_class_pima_command_nb_parameters); + + /* Fill the command container. First the length of the total header and payload. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_LENGTH, requested_length); + + /* Then the type of container : a command block here. */ + _ux_utility_short_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_TYPE, UX_HOST_CLASS_PIMA_CT_COMMAND_BLOCK); + + /* Now the command code to send. */ + _ux_utility_short_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_CODE, (USHORT)command.ux_host_class_pima_command_operation_code); + + /* Put the transaction ID. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_TRANSACTION_ID, + pima -> ux_host_class_pima_transaction_id++); + + /* Then fill in the parameters. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_COMMAND_HEADER_PARAMETER_1, + command.ux_host_class_pima_command_parameter_1); + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = ptp_payload; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* Set the thumb transfer status to aborted. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED; + + /* There was an error, return to the caller. */ + return(status); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Check for completion of transfer. If the transfer is partial, return to caller. + Partial transfer is not OK. */ + if (requested_length == transfer_request -> ux_transfer_request_actual_length) + { + + /* Obtain the first packet. This packet contains the header and some data. + We use the Bulk In pipe for receiving data .. */ + transfer_request = &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Get the pointer to the ptp payload. */ + ptp_payload = pima -> ux_host_class_pima_container ; + + /* Calculate the requested length for this payload. */ + requested_length = UX_HOST_CLASS_PIMA_CONTAINER_SIZE; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = ptp_payload; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* Set the thumb transfer status to aborted. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED; + + /* There was an error, return to the caller. */ + return(status); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Ensure transfer length is greater than the size of the header. */ + if (transfer_request -> ux_transfer_request_actual_length <= UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE) + + /* We have a malformed packet. Return error. */ + return(UX_CLASS_MALFORMED_PACKET_RECEIVED_ERROR); + + /* Ensure there's enough room in the application's buffer. */ + if (thumb_buffer_length < transfer_request -> ux_transfer_request_actual_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE) + + /* Not enough room. Return error. */ + return(UX_MEMORY_INSUFFICIENT); + + /* We need to skip the header. Copying the necessary partial memory only. */ + _ux_utility_memory_copy(thumb_buffer, ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE, + transfer_request -> ux_transfer_request_actual_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE); + + /* Update the actual length. */ + *thumb_actual_length = transfer_request -> ux_transfer_request_actual_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE; + + /* And the offset. */ + object -> ux_host_class_pima_object_offset += transfer_request -> ux_transfer_request_actual_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE; + + } + else + + /* We got a premature error. */ + return(UX_HOST_CLASS_PIMA_RC_INCOMPLETE_TRANSFER); + } + + else + { + + /* We use the Bulk In pipe for receiving data .. */ + transfer_request = &pima -> ux_host_class_pima_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* We read a complete block. */ + while(thumb_buffer_length != 0) + { + + /* It may take several transactions. */ + if (thumb_buffer_length > UX_HOST_CLASS_PIMA_MAX_PAYLOAD) + + /* Set the requested length to the payload maximum. */ + requested_length = UX_HOST_CLASS_PIMA_MAX_PAYLOAD; + + else + + /* We can use the user supplied length to complete this request. */ + requested_length = thumb_buffer_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = thumb_buffer; + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* Set the thumb transfer status to aborted. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_ABORTED; + + /* There was an error, return to the caller. */ + return(status); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Update the object length expected by the user with what we actually received. */ + thumb_buffer_length -= transfer_request -> ux_transfer_request_actual_length; + + /* Update the actual length. */ + *thumb_actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* And the offset. */ + object -> ux_host_class_pima_object_offset += transfer_request -> ux_transfer_request_actual_length; + + /* Check to see if we are at the end of the object. */ + if (object -> ux_host_class_pima_object_offset == object -> ux_host_class_pima_object_thumb_compressed_size) + + /* The transfer for this transaction is completed. */ + object -> ux_host_class_pima_object_transfer_status = UX_HOST_CLASS_PIMA_OBJECT_TRANSFER_STATUS_COMPLETED; + + } + + } + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_pima_write.c b/common/usbx_host_classes/src/ux_host_class_pima_write.c new file mode 100644 index 0000000..2c464d8 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_pima_write.c @@ -0,0 +1,297 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Pima Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_pima.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_pima_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a data payload to the Pima device. This */ +/* function first write a header followed by some data. */ +/* */ +/* INPUT */ +/* */ +/* pima Pointer to pima class */ +/* data_pointer Pointer to data to write */ +/* data_length Length of data to write */ +/* operation_code Code to send in header (this */ +/* is from the command block */ +/* max_payload_data Maximum data sent in one load */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_host_stack_endpoint_reset Reset endpoint */ +/* _ux_utility_memory_copy Copy memory */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_long_put Put a long 32 bit value */ +/* _ux_utility_short_put Put a short 16 bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_pima_write(UX_HOST_CLASS_PIMA *pima, UCHAR *data_pointer, + ULONG data_length, + ULONG operation_code, + ULONG max_payload_length) + +{ + +UX_TRANSFER *transfer_request; +UINT status; +UCHAR *ptp_payload; +ULONG requested_length; +ULONG payload_length; + + UX_PARAMETER_NOT_USED(operation_code); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PIMA_WRITE, pima, data_pointer, data_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We use the Bulk Out pipe for receiving data .. */ + transfer_request = &pima -> ux_host_class_pima_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Get the pointer to the ptp payload. */ + ptp_payload = pima -> ux_host_class_pima_container ; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = ptp_payload; + + /* Fill in the header values. Start with the length of the container. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_LENGTH, data_length + UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE); + + /* Check for remainder in last packet. */ + if (((data_length + UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE) % pima -> ux_host_class_pima_bulk_out_endpoint -> ux_endpoint_descriptor.wMaxPacketSize) == 0) + + /* We have a ZLP condition on a OUT. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_OUT; + else + + /* Do not expect a ZLP. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_NONE; + + /* Container type is a data type. */ + *(ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_TYPE) = UX_HOST_CLASS_PIMA_CT_DATA_BLOCK; + + /* Put the operation code. */ + *(ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_CODE) = (UCHAR)pima -> ux_host_class_pima_operation_code; + + /* Store the transaction ID. */ + _ux_utility_long_put(ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_TRANSACTION_ID, + pima -> ux_host_class_pima_transaction_id); + + /* Calculate the requested length in the first container. */ + requested_length = data_length + UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE; + + /* Can we fill the container ? */ + if(requested_length > UX_HOST_CLASS_PIMA_CONTAINER_SIZE) + + /* We have more data in the payload than the first container so adjust the length. */ + requested_length = UX_HOST_CLASS_PIMA_CONTAINER_SIZE; + + /* Add the data payload to fill that container. */ + _ux_utility_memory_copy(ptp_payload + UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE, data_pointer, + requested_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE); + + /* Initialize the transfer of that container. */ + transfer_request -> ux_transfer_request_requested_length = requested_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + + /* There was an error, return to the caller. */ + return(status); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Isolate the length of the data payload that still needs to be sent. */ + data_length -= (requested_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE); + + /* Adjust the data payload pointer. */ + data_pointer += (requested_length - UX_HOST_CLASS_PIMA_DATA_HEADER_SIZE); + + /* Now we can send the data to the device. */ + while(data_length) + { + + /* Check if need to split the data payload into smaller packets. */ + if (data_length > max_payload_length) + + /* We cannot send everything in this payload. */ + payload_length = max_payload_length; + else + + /* Either this is the last packet or we we have a small packet to send. */ + payload_length = data_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = payload_length; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* There was an error, return to the caller. */ + return(status); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Check for completion of transfer. If the transfer is partial, return to caller. + Partial transfer is not OK. */ + if (payload_length != transfer_request -> ux_transfer_request_actual_length) + return(UX_TRANSFER_ERROR); + + /* Adjust the total length to transfer. */ + data_length -= payload_length; + + /* Adjust the data pointer. */ + data_pointer += payload_length; + + } + + /* If we have a ZLP condition, write the device one more time with a zero packet. */ + if (pima -> ux_host_class_pima_zlp_flag == UX_HOST_CLASS_PIMA_ZLP_OUT) + { + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PIMA_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_in_endpoint); + + /* The endpoint was halted by a transfer error and needs to be reset. */ + _ux_host_stack_endpoint_reset(pima -> ux_host_class_pima_bulk_out_endpoint); + + /* There was an error, return to the caller. */ + return(status); + } + + /* Reset the ZLP. */ + pima -> ux_host_class_pima_zlp_flag = UX_HOST_CLASS_PIMA_ZLP_NONE; + } + } + + /* We have finished receiving the data. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_printer_activate.c b/common/usbx_host_classes/src/ux_host_class_printer_activate.c new file mode 100644 index 0000000..2cc8787 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_printer_activate.c @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_printer.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to activate the class. */ +/* */ +/* INPUT */ +/* */ +/* command Printer class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_printer_configure Configure printer class */ +/* _ux_host_class_printer_endpoints_get Get endpoints of printer */ +/* _ux_host_class_printer_name_get Get printer name */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_create Create printer semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_printer_entry Entry of printer class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_printer_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_INTERFACE *interface; +UX_HOST_CLASS_PRINTER *printer; +UINT status; + + + /* The printer is always activated by the interface descriptor and not the + device descriptor. */ + interface = (UX_INTERFACE *) command -> ux_host_class_command_container; + + /* Obtain memory for this class instance. */ + printer = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS_PRINTER)); + if (printer == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance. */ + printer -> ux_host_class_printer_class = command -> ux_host_class_command_class_ptr; + + /* Store the interface container into the printer class instance. */ + printer -> ux_host_class_printer_interface = interface; + + /* Store the device container into the printer class instance. */ + printer -> ux_host_class_printer_device = interface -> ux_interface_configuration -> ux_configuration_device; + + /* This instance of the device must also be stored in the interface container. */ + interface -> ux_interface_class_instance = (VOID *) printer; + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(printer -> ux_host_class_printer_class, (VOID *) printer); + + /* Configure the printer. */ + status = _ux_host_class_printer_configure(printer); + + /* Get the name of the printer from the 1284 descriptor. */ + if (status == UX_SUCCESS) + status = _ux_host_class_printer_name_get(printer); + + /* Get the printer endpoint(s). We may need to search for Bulk Out and Bulk In endpoints. */ + if (status == UX_SUCCESS) + status = _ux_host_class_printer_endpoints_get(printer); + + /* Create the semaphore to protect 2 threads from accessing the same printer instance. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&printer -> ux_host_class_printer_semaphore, "ux_host_class_printer_semaphore", 1); + if (status != UX_SUCCESS) + status = UX_SEMAPHORE_ERROR; + } + + /* Success things. */ + if (status == UX_SUCCESS) + { + + /* Mark the printer as live now. */ + printer -> ux_host_class_printer_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, printer -> ux_host_class_printer_class, (VOID *) printer); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_ACTIVATE, printer, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, printer, 0, 0, 0) + + /* Return success. */ + return(UX_SUCCESS); + } + + /* On error, free resources. */ + _ux_host_stack_class_instance_destroy(printer -> ux_host_class_printer_class, (VOID *) printer); + interface -> ux_interface_class_instance = UX_NULL; + _ux_utility_memory_free(printer); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_printer_configure.c b/common/usbx_host_classes/src/ux_host_class_printer_configure.c new file mode 100644 index 0000000..00b7d1d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_printer_configure.c @@ -0,0 +1,145 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_printer.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to the */ +/* printer. Once the printer is configured, its interface will be */ +/* activated. The bulk endpoints enumerated(1 IN, 1 OUT ). */ +/* */ +/* INPUT */ +/* */ +/* printer Pointer to printer class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get Get interface */ +/* _ux_host_stack_device_configuration_get Get configuration */ +/* _ux_host_stack_device_configuration_select Select configuration */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_printer_activate Printer class activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_printer_configure(UX_HOST_CLASS_PRINTER *printer) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_DEVICE *parent_device; + + + /* If the device has been configured already, we don't need to do it + again. */ + if (printer -> ux_host_class_printer_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* A printer normally has one configuration. So retrieve the 1st configuration + only. */ + status = _ux_host_stack_device_configuration_get(printer -> ux_host_class_printer_device, 0, &configuration); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, printer -> ux_host_class_printer_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check the printer power source and check the parent power source for + incompatible connections. */ + if (printer -> ux_host_class_printer_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* Get parent device pointer. */ + parent_device = printer -> ux_host_class_printer_device -> ux_device_parent; + + /* If the device is NULL, the parent is the root printer and we don't have to worry + if the parent is not the root printer, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, printer, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration. */ + status = _ux_host_stack_device_configuration_select(configuration); + if (status != UX_SUCCESS) + return(status); + + /* If the operation went well, the printer default alternate setting for the printer interface is + active and the interrupt endpoint is now enabled. We have to memorize the first interface since + the interrupt endpoint is hooked to it. */ + status = _ux_host_stack_configuration_interface_get(configuration, 0, 0, &printer -> ux_host_class_printer_interface); + if (status != UX_SUCCESS) + { + + /* Store the instance in the interface container, this is for the USB stack + when it needs to invoke the class. */ + printer -> ux_host_class_printer_interface -> ux_interface_class_instance = (VOID *) printer; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_printer_deactivate.c b/common/usbx_host_classes/src/ux_host_class_printer_deactivate.c new file mode 100644 index 0000000..1327c57 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_printer_deactivate.c @@ -0,0 +1,136 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_printer.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the printer has been */ +/* removed from the bus either directly or indirectly. The bulk in\out */ +/* pipes will be destroyed and the instanced removed. */ +/* */ +/* INPUT */ +/* */ +/* command Printer class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort endpoint transfer */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_utility_thread_schedule_other Schedule other threads */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_printer_entry Entry of printer class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_printer_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_PRINTER *printer; +UINT status; + + + /* Get the instance for this class. */ + printer = (UX_HOST_CLASS_PRINTER *) command -> ux_host_class_command_instance; + + /* The printer is being shut down. */ + printer -> ux_host_class_printer_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* We need to abort transactions on the bulk out pipe. */ + _ux_host_stack_endpoint_transfer_abort(printer -> ux_host_class_printer_bulk_out_endpoint); + + /* If the printer is bidirectional, we need to abort transactions on the bulk in pipe. */ + if (printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL) + _ux_host_stack_endpoint_transfer_abort(printer -> ux_host_class_printer_bulk_in_endpoint); + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(printer -> ux_host_class_printer_class, (VOID *) printer); + + /* Destroy the semaphore. */ + _ux_utility_semaphore_delete(&printer -> ux_host_class_printer_semaphore); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, printer -> ux_host_class_printer_class, (VOID *) printer); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_DEACTIVATE, printer, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(printer); + + /* Free the printer instance memory. */ + _ux_utility_memory_free(printer); + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_printer_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_printer_endpoints_get.c new file mode 100644 index 0000000..6e86543 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_printer_endpoints_get.c @@ -0,0 +1,163 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_printer.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function search for the handle of the bulk out endpoint and */ +/* optionally the bulk in endpoint of the printer is bidirectional. */ +/* */ +/* INPUT */ +/* */ +/* printer Pointer to printer class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_printer_activate Activate printer class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_printer_endpoints_get(UX_HOST_CLASS_PRINTER *printer) +{ + +UINT status; +UINT endpoint_index; +UX_ENDPOINT *endpoint; + + + /* Search the bulk OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get interface endpoint. */ + status = _ux_host_stack_interface_endpoint_get(printer -> ux_host_class_printer_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the OUT direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + + /* We have found the bulk endpoint, save it. */ + printer -> ux_host_class_printer_bulk_out_endpoint = endpoint; + break; + } + } + } + + /* The bulk out endpoint is mandatory. */ + if (printer -> ux_host_class_printer_bulk_out_endpoint == UX_NULL) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, printer, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search the bulk IN endpoint. This endpoint is optional and only valid for + bidirectional printers. It is attached to the interface container. */ + if (printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol == + UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL) + { + + for (endpoint_index = 0; endpoint_index < printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + status = _ux_host_stack_interface_endpoint_get(printer -> ux_host_class_printer_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the bulk endpoint, save it. */ + printer -> ux_host_class_printer_bulk_in_endpoint = endpoint; + break; + } + } + } + + /* The bulk in endpoint is not mandatory. */ + if ((printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL) + && (printer -> ux_host_class_printer_bulk_in_endpoint == UX_NULL)) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, printer, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + } + + /* All endpoints have been mounted. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_printer_entry.c b/common/usbx_host_classes/src/ux_host_class_printer_entry.c new file mode 100644 index 0000000..ee7fa18 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_printer_entry.c @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_printer.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the printer class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* printer on the bus or when the USB printer is removed. */ +/* */ +/* INPUT */ +/* */ +/* command Printer class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_printer_activate Activate printer class */ +/* _ux_host_class_printer_deactivate Deactivate printer class */ +/* */ +/* CALLED BY */ +/* */ +/* Printer Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_printer_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) && + (command -> ux_host_class_command_class == UX_HOST_CLASS_PRINTER_CLASS)) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_printer_activate(command); + return(status); + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_printer_deactivate(command); + return(status); + + default: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_printer_name_get.c b/common/usbx_host_classes/src/ux_host_class_printer_name_get.c new file mode 100644 index 0000000..74d2e7a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_printer_name_get.c @@ -0,0 +1,197 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_printer.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_name_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the printer name. The name is used by the */ +/* application layer to identify the printer and loads its handler. */ +/* */ +/* INPUT */ +/* */ +/* printer Pointer to printer class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_compare Compare memory block */ +/* _ux_utility_memory_copy Copy memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_short_get_big_endian Get 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_printer_name_get(UX_HOST_CLASS_PRINTER *printer) +{ + +UCHAR * descriptor_buffer; +UCHAR * printer_name_buffer; +UCHAR * printer_name; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +USHORT descriptor_length; +UINT printer_name_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_NAME_GET, printer, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &printer -> ux_host_class_printer_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the 1284 descriptor. */ + descriptor_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PRINTER_DESCRIPTOR_LENGTH); + if(descriptor_buffer == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Create a transfer request for the GET_DEVICE_ID request. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor_buffer; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_PRINTER_DESCRIPTOR_LENGTH; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PRINTER_GET_DEVICE_ID; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer. We do not check for entire length as it may vary. */ + if(status == UX_SUCCESS) + { + + /* Cannot use descriptor buffer, so copy it to 1284 buffer. */ + printer_name_buffer = descriptor_buffer; + + /* Retrieve the printer name which is a USHORT at the beginning of the returned buffer. */ + descriptor_length = (USHORT)_ux_utility_short_get_big_endian(printer_name_buffer); + + /* Point the name buffer after the length. */ + printer_name_buffer += 2; + + /* Parse the name for a tag which is in the form DES: or DESCRIPTOR: */ + while (descriptor_length != 0) + { + + if (descriptor_length > 12) + { + + /* Compare the current pointer position with the DESCRIPTOR: tag. */ + if (_ux_utility_memory_compare(printer_name_buffer, UX_HOST_CLASS_PRINTER_TAG_DESCRIPTION, 12) == UX_SUCCESS) + { + + printer_name_buffer += 12; + descriptor_length = (USHORT)(descriptor_length - 12); + break; + } + } + + if (descriptor_length > 4) + { + + /* Compare the current pointer position with the DES: tag. */ + if (_ux_utility_memory_compare(printer_name_buffer, UX_HOST_CLASS_PRINTER_TAG_DES, 4) == UX_SUCCESS) + { + + printer_name_buffer += 4; + descriptor_length = (USHORT)(descriptor_length - 4); + break; + } + } + + /* And reduce the remaining length by 1. */ + descriptor_length--; + + /* Increment the descriptor pointer. */ + printer_name_buffer++; + } + + /* If the length remaining is 0, we have not found the descriptor tag we wanted. */ + if (descriptor_length == 0) + { + + /* Use the generic USB printer name. */ + _ux_utility_memory_copy(printer -> ux_host_class_printer_name, UX_HOST_CLASS_PRINTER_GENERIC_NAME, 11); + } + else + { + + /* We have found a tag and the name is right after delimited by ; or a 0. */ + printer_name = printer -> ux_host_class_printer_name; + printer_name_length = UX_HOST_CLASS_PRINTER_NAME_LENGTH; + + /* Parse the name and only copy the name until the max length is reached + or the delimiter is reached. */ + while ((descriptor_length--) && (printer_name_length--)) + { + + /* Check for the delimiter. */ + if((*printer_name_buffer == 0) || (*printer_name_buffer == ';')) + break; + else + /* Copy the name of the printer to the printer instance character + by character. */ + *printer_name++ = *printer_name_buffer++; + } + } + } + + /* Free all used resources. */ + _ux_utility_memory_free(descriptor_buffer); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_printer_read.c b/common/usbx_host_classes/src/ux_host_class_printer_read.c new file mode 100644 index 0000000..42a1076 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_printer_read.c @@ -0,0 +1,227 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_printer.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the printer interface. The call is */ +/* blocking and only returns when there is either an error or when */ +/* the transfer is complete. */ +/* */ +/* A read is only allowed on bidirectional printers. */ +/* */ +/* INPUT */ +/* */ +/* printer Pointer to printer class */ +/* data_pointer Pointer to buffer */ +/* requested_length Requested data read */ +/* actual_length Actual data read */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify the class instance */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_printer_read (UX_HOST_CLASS_PRINTER *printer, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_READ, printer, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (printer -> ux_host_class_printer_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, printer, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* Check if the printer is bidirectional. */ + if (printer -> ux_host_class_printer_interface -> ux_interface_descriptor.bInterfaceProtocol != + UX_HOST_CLASS_PRINTER_PROTOCOL_BI_DIRECTIONAL) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } + + /* Start by resetting the actual length of the transfer to zero. */ + *actual_length = 0; + + /* Get the pointer to the bulk in endpoint in the transfer_request. */ + transfer_request = &printer -> ux_host_class_printer_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Perform a transfer on the bulk in endpoint until either the transfer is + completed or until there is an error. */ + while (requested_length) + { + + /* Program the maximum authorized length for this transfer request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer_request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PRINTER_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer request in case some data was actually received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + + /* There was a non transfer error, no partial transfer to be checked. */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually received and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + + /* Return success to caller. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to receive. */ + requested_length -= transfer_request_length; + } + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_printer_soft_reset.c b/common/usbx_host_classes/src/ux_host_class_printer_soft_reset.c new file mode 100644 index 0000000..450ce8d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_printer_soft_reset.c @@ -0,0 +1,125 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_printer.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_soft_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a soft reset of the printer in case the */ +/* printer gets into an error mode. */ +/* */ +/* INPUT */ +/* */ +/* printer Pointer to printer class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_printer_soft_reset(UX_HOST_CLASS_PRINTER *printer) +{ + + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_SOFT_RESET, printer, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (printer -> ux_host_class_printer_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, printer, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &printer -> ux_host_class_printer_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Create a transfer_request for the SOFT_RESET request. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PRINTER_SOFT_RESET; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_printer_status_get.c b/common/usbx_host_classes/src/ux_host_class_printer_status_get.c new file mode 100644 index 0000000..da8f071 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_printer_status_get.c @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_printer.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_status_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the printer status. The printer status is */ +/* similar to the LPT status (1284 standard). */ +/* */ +/* INPUT */ +/* */ +/* printer Pointer to printer class */ +/* printer_status Pointer to return status */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify the class instance */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_long_get Get 32-bit long word */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_printer_status_get(UX_HOST_CLASS_PRINTER *printer, ULONG *printer_status) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +UCHAR * printer_status_buffer; + + /* Ensure the instance is valid. */ + if (printer -> ux_host_class_printer_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, printer, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* We need to get the default control endpoint transfer_request pointer. */ + control_endpoint = &printer -> ux_host_class_printer_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the descriptor. */ + printer_status_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PRINTER_STATUS_LENGTH); + if (printer_status_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + return(UX_MEMORY_INSUFFICIENT); + } + + /* Create a transfer_request for the GET_STATUS request. */ + transfer_request -> ux_transfer_request_data_pointer = printer_status_buffer; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_PRINTER_STATUS_LENGTH; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PRINTER_GET_STATUS; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && + (transfer_request -> ux_transfer_request_actual_length > 0) && + (transfer_request -> ux_transfer_request_actual_length <= UX_HOST_CLASS_PRINTER_STATUS_LENGTH)) + { + + /* Retrieve the printer status and translate it locally for endianness. */ + *printer_status = printer_status_buffer[0]; + if (transfer_request -> ux_transfer_request_actual_length > 1) + *printer_status |= (ULONG)(printer_status_buffer[1] << 8); + if (transfer_request -> ux_transfer_request_actual_length > 2) + *printer_status |= (ULONG)(printer_status_buffer[2] << 16); + if (transfer_request -> ux_transfer_request_actual_length > 3) + *printer_status |= (ULONG)(printer_status_buffer[3] << 24); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_STATUS_GET, printer, *printer_status, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + } + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, status); + } + + /* Free all used resources. */ + _ux_utility_memory_free(printer_status_buffer); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_printer_write.c b/common/usbx_host_classes/src/ux_host_class_printer_write.c new file mode 100644 index 0000000..8fb6c6f --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_printer_write.c @@ -0,0 +1,206 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Printer Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_printer.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_printer_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the printer interface. The call is blocking */ +/* and only returns when there is either an error or when the transfer */ +/* is complete. */ +/* */ +/* INPUT */ +/* */ +/* printer Pointer to printer class */ +/* data_pointer Pointer to data to write */ +/* requested_length Length of data to write */ +/* actual_length Actual length of data written */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_printer_write(UX_HOST_CLASS_PRINTER *printer, UCHAR * data_pointer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PRINTER_WRITE, printer, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (printer -> ux_host_class_printer_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, printer, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&printer -> ux_host_class_printer_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* Start by resetting the actual length of the transfer. */ + *actual_length = 0; + + /* Get the pointer to the bulk out endpoint transfer request. */ + transfer_request = &printer -> ux_host_class_printer_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Perform a transfer on the bulk out endpoint until either the transfer is + completed or when there is an error. */ + while (requested_length) + { + + /* Program the maximum authorized length for this transfer_request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PRINTER_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer_request in case some data actually went out. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be sent. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually sent and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + + /* Return success. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to send out. */ + requested_length -= transfer_request_length; + } + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&printer -> ux_host_class_printer_semaphore); + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_activate.c b/common/usbx_host_classes/src/ux_host_class_prolific_activate.c new file mode 100644 index 0000000..44883af --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_activate.c @@ -0,0 +1,192 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates the prolific instance, configure the device. */ +/* */ +/* INPUT */ +/* */ +/* command DLC class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_prolific_configure Configure prolific class */ +/* _ux_host_class_prolific_endpoints_get Get endpoints of prolific */ +/* _ux_host_class_prolific_setup Set up prolific device */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_create Create prolific semaphore */ +/* _ux_host_class_prolific_ioctl IOCTL function for DLC */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_prolific_entry Entry of prolific class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_DEVICE *device; +UX_HOST_CLASS_PROLIFIC *prolific; +UX_HOST_CLASS_PROLIFIC_LINE_CODING line_coding; +UX_HOST_CLASS_PROLIFIC_LINE_STATE line_state; +UINT status; + + /* The prolific class is always activated by the device descriptor. */ + device = (UX_DEVICE *) command -> ux_host_class_command_container; + + /* Obtain memory for this class instance. */ + prolific = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, sizeof(UX_HOST_CLASS_PROLIFIC)); + if (prolific == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance. */ + prolific -> ux_host_class_prolific_class = command -> ux_host_class_command_class_ptr; + + /* Store the device container into the prolific class instance. */ + prolific -> ux_host_class_prolific_device = device; + + /* Store the instance in the device container, this is for the USBX stack + when it needs to invoke the class for deactivation. */ + device -> ux_device_class_instance = (VOID *) prolific; + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(prolific -> ux_host_class_prolific_class, (VOID *) prolific); + + /* Configure the prolific. */ + status = _ux_host_class_prolific_configure(prolific); + + /* Get the prolific endpoint(s). We need to search for Bulk Out and Bulk In endpoints + and the interrupt endpoint. */ + if (status == UX_SUCCESS) + status = _ux_host_class_prolific_endpoints_get(prolific); + + /* Go on if success. */ + if (status == UX_SUCCESS) + { + + /* Store chip version for further reference. */ + prolific -> ux_host_class_prolific_version = device -> ux_device_descriptor.bcdDevice; + + /* Mark the prolific instance as mounting now. */ + prolific -> ux_host_class_prolific_state = UX_HOST_CLASS_INSTANCE_MOUNTING; + + /* The prolific chip needs to be setup properly. */ + status = _ux_host_class_prolific_setup(prolific); + } + + /* Set the default values to the device, first line coding. */ + if (status == UX_SUCCESS) + { + line_coding.ux_host_class_prolific_line_coding_dter = UX_HOST_CLASS_PROLIFIC_LINE_CODING_DEFAULT_RATE; + line_coding.ux_host_class_prolific_line_coding_stop_bit = UX_HOST_CLASS_PROLIFIC_LINE_CODING_STOP_BIT_0; + line_coding.ux_host_class_prolific_line_coding_parity = UX_HOST_CLASS_PROLIFIC_LINE_CODING_PARITY_NONE; + line_coding.ux_host_class_prolific_line_coding_data_bits = UX_HOST_CLASS_PROLIFIC_LINE_CODING_DEFAULT_DATA_BIT; + status = _ux_host_class_prolific_ioctl(prolific, UX_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_CODING, (VOID *) &line_coding); + } + + /* Set the default values to the device, line state. For the Prolific chip to detect disconnection + and reconnection, RTS is low. */ + if (status == UX_SUCCESS) + { + line_state.ux_host_class_prolific_line_state_rts = 0; + line_state.ux_host_class_prolific_line_state_dtr = 1; + status = _ux_host_class_prolific_ioctl(prolific, UX_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_STATE, (VOID *) &line_state); + } + + /* Create the semaphore to protect 2 threads from accessing the same prolific instance. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&prolific -> ux_host_class_prolific_semaphore, "ux_host_class_prolific_semaphore", 1); + if (status != UX_SUCCESS) + status = UX_SEMAPHORE_ERROR; + } + + /* Success things. */ + if (status == UX_SUCCESS) + { + + /* Mark the prolific instance as live now. */ + prolific -> ux_host_class_prolific_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, prolific -> ux_host_class_prolific_class, (VOID *) prolific); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_ACTIVATE, prolific, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, prolific, 0, 0, 0) + + /* Return success. */ + return(UX_SUCCESS); + } + + /* There was a problem during the configuration, so free the resources. */ + /* The last resource, semaphore is not created or created error, no need to free. */ + _ux_host_stack_class_instance_destroy(prolific -> ux_host_class_prolific_class, (VOID *) prolific); + device -> ux_device_class_instance = UX_NULL; + _ux_utility_memory_free(prolific); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_command.c b/common/usbx_host_classes/src/ux_host_class_prolific_command.c new file mode 100644 index 0000000..8d8551f --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_command.c @@ -0,0 +1,119 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_command PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will send a command to the Prolific device. */ +/* The command can be one of the following : */ +/* SET_CONTROL */ +/* SET_LINE */ +/* SEND_BREAK */ +/* */ +/* */ +/* INPUT */ +/* */ +/* prolific Pointer to prolific class */ +/* command command value */ +/* value value to be sent in the */ +/* command request */ +/* data_buffer buffer to be sent */ +/* data_length length of the buffer to send */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_command(UX_HOST_CLASS_PROLIFIC *prolific, ULONG command, + ULONG value, UCHAR *data_buffer, ULONG data_length) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; + + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &prolific -> ux_host_class_prolific_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&prolific -> ux_host_class_prolific_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + + /* Something went wrong. */ + return(status); + + /* Create a transfer_request for the request. */ + transfer_request -> ux_transfer_request_data_pointer = data_buffer; + transfer_request -> ux_transfer_request_requested_length = data_length; + transfer_request -> ux_transfer_request_function = command; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = value; + transfer_request -> ux_transfer_request_index = prolific -> ux_host_class_prolific_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_configure.c b/common/usbx_host_classes/src/ux_host_class_prolific_configure.c new file mode 100644 index 0000000..576aac0 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_configure.c @@ -0,0 +1,153 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to the */ +/* prolific. Once the prolific is configured, its interface will be */ +/* activated. The bulk endpoints (1 IN, 1 OUT ) and the optional */ +/* interrupt endpoint are enumerated. */ +/* */ +/* INPUT */ +/* */ +/* prolific Pointer to prolific class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get Get interface */ +/* _ux_host_stack_device_configuration_get Get configuration */ +/* _ux_host_stack_device_configuration_select Select configuration */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_prolific_activate Prolific class activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_configure(UX_HOST_CLASS_PROLIFIC *prolific) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_DEVICE *parent_device; + + + /* If the device has been configured already, we don't need to do it + again. */ + if (prolific -> ux_host_class_prolific_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* A prolific normally has one configuration. So retrieve the 1st configuration + only. */ + status = _ux_host_stack_device_configuration_get(prolific -> ux_host_class_prolific_device, 0, &configuration); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, prolific -> ux_host_class_prolific_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check the prolific power source and check the parent power source for + incompatible connections. */ + if (prolific -> ux_host_class_prolific_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* Get parent device pointer. */ + parent_device = prolific -> ux_host_class_prolific_device -> ux_device_parent; + + /* If the device is NULL, the parent is the root prolific and we don't have to worry + if the parent is not the root prolific, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, prolific, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration. */ + status = _ux_host_stack_device_configuration_select(configuration); + if (status != UX_SUCCESS) + return(status); + + /* If the operation went well, the prolific default alternate setting for the prolific interface is + active and the interrupt endpoint is now enabled. We have to memorize the first interface since + the interrupt endpoint is hooked to it. */ + status = _ux_host_stack_configuration_interface_get(configuration, 0, 0, &prolific -> ux_host_class_prolific_interface); + + /* Check status for error. */ + if (status == UX_SUCCESS) + { + + /* Store the instance in the interface container, this is for the USB stack + when it needs to invoke the class. */ + prolific -> ux_host_class_prolific_interface -> ux_interface_class_instance = (VOID *) prolific; + + /* Store the class container in the interface. The device has the correct class, duplicate it to the + interface. */ + prolific -> ux_host_class_prolific_interface -> ux_interface_class = prolific -> ux_host_class_prolific_device -> ux_device_class ; + + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_deactivate.c b/common/usbx_host_classes/src/ux_host_class_prolific_deactivate.c new file mode 100644 index 0000000..9b168a1 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_deactivate.c @@ -0,0 +1,163 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the prolific has been */ +/* removed from the bus either directly or indirectly. The bulk in\out */ +/* and optional interrupt pipes will be destroyed and the instance */ +/* removed. */ +/* */ +/* INPUT */ +/* */ +/* command Prolific class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_endpoint_transfer_abort Abort endpoint transfer */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_utility_thread_schedule_other Schedule other threads */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_prolific_entry Entry of prolific class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_PROLIFIC *prolific; +UX_TRANSFER *transfer_request; +UINT status; + + + /* Get the instance for this class. */ + prolific = (UX_HOST_CLASS_PROLIFIC *) command -> ux_host_class_command_instance; + + /* The prolific is being shut down. */ + prolific -> ux_host_class_prolific_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&prolific -> ux_host_class_prolific_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* If the interrupt endpoint is defined, clean any pending transfer. */ + if (prolific -> ux_host_class_prolific_interrupt_endpoint != UX_NULL) + { + + /* Wait for any current transfer to be out of pending. */ + transfer_request = &prolific -> ux_host_class_prolific_interrupt_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + + /* And abort any transfer. */ + _ux_host_stack_endpoint_transfer_abort(prolific -> ux_host_class_prolific_interrupt_endpoint); + + /* And free the memory used by the interrupt endpoint. */ + _ux_utility_memory_free(transfer_request -> ux_transfer_request_data_pointer); + + } + + + /* First we take care of cleaning endpoint IN. */ + transfer_request = &prolific -> ux_host_class_prolific_bulk_in_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(prolific -> ux_host_class_prolific_bulk_in_endpoint); + + + /* Then endpoint OUT. */ + transfer_request = &prolific -> ux_host_class_prolific_bulk_out_endpoint -> ux_endpoint_transfer_request; + if (transfer_request -> ux_transfer_request_completion_code == UX_TRANSFER_STATUS_PENDING) + + /* We need to abort transactions on the bulk Out pipe. */ + _ux_host_stack_endpoint_transfer_abort(prolific -> ux_host_class_prolific_bulk_out_endpoint); + + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(prolific -> ux_host_class_prolific_class, (VOID *) prolific); + + /* Destroy the semaphore. */ + _ux_utility_semaphore_delete(&prolific -> ux_host_class_prolific_semaphore); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, prolific -> ux_host_class_prolific_class, (VOID *) prolific); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_DEACTIVATE, prolific, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(prolific); + + /* Free the prolific instance memory. */ + _ux_utility_memory_free(prolific); + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_prolific_endpoints_get.c new file mode 100644 index 0000000..f4d6463 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_endpoints_get.c @@ -0,0 +1,248 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function distinguishes for either the Data or Control Class. */ +/* For the data class, we mount the bulk in and bulk out endpoints. */ +/* For the control class, we mount the optional interrupt endpoint. */ +/* */ +/* INPUT */ +/* */ +/* prolific Pointer to prolific class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* _ux_utility_memory_allocate Allocate memory */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_prolific_activate Activate prolific class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_endpoints_get(UX_HOST_CLASS_PROLIFIC *prolific) +{ + +UINT status; +UINT endpoint_index; +UX_ENDPOINT *endpoint; +UX_TRANSFER *transfer_request; + + + /* Search the bulk OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < prolific -> ux_host_class_prolific_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get interface endpoint. */ + status = _ux_host_stack_interface_endpoint_get(prolific -> ux_host_class_prolific_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the OUT direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + + /* We have found the bulk endpoint, save it. */ + prolific -> ux_host_class_prolific_bulk_out_endpoint = endpoint; + break; + } + } + } + + /* The bulk out endpoint is mandatory. */ + if (prolific -> ux_host_class_prolific_bulk_out_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, prolific, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search the bulk IN endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < prolific -> ux_host_class_prolific_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + status = _ux_host_stack_interface_endpoint_get(prolific -> ux_host_class_prolific_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the bulk endpoint, save it. */ + prolific -> ux_host_class_prolific_bulk_in_endpoint = endpoint; + break; + } + } + } + + /* The bulk in endpoint is mandatory. */ + if (prolific -> ux_host_class_prolific_bulk_in_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, prolific, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search the Interrupt endpoint. It is mandatory. */ + for (endpoint_index = 0; endpoint_index < prolific -> ux_host_class_prolific_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + status = _ux_host_stack_interface_endpoint_get(prolific -> ux_host_class_prolific_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is Interrupt and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the interrupt endpoint, save it. */ + prolific -> ux_host_class_prolific_interrupt_endpoint = endpoint; + + /* The endpoint is correct, Fill in the transfer request with the length requested for this endpoint. */ + transfer_request = &prolific -> ux_host_class_prolific_interrupt_endpoint -> ux_endpoint_transfer_request; + transfer_request -> ux_transfer_request_requested_length = prolific -> ux_host_class_prolific_interrupt_endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + transfer_request -> ux_transfer_request_actual_length = 0; + + /* The direction is always IN for the CDC interrupt endpoint. */ + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN; + + /* There is a callback function associated with the transfer request, so we need the class instance. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) prolific; + + /* Interrupt transactions have a completion routine. */ + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_prolific_transfer_request_completed; + + /* Obtain a buffer for this transaction. The buffer will always be reused. */ + transfer_request -> ux_transfer_request_data_pointer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + transfer_request -> ux_transfer_request_requested_length); + + /* If the endpoint is available and we have memory, we start the interrupt endpoint. */ + if (transfer_request -> ux_transfer_request_data_pointer != UX_NULL) + { + + /* The transfer on the interrupt endpoint can be started. */ + status = _ux_host_stack_transfer_request(transfer_request); + + } + + else + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We must return an error. */ + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + break; + } + } + } + + /* The interrupt endpoint is mandatory. */ + if (prolific -> ux_host_class_prolific_interrupt_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, prolific, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + else + + /* All endpoints have been mounted. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_entry.c b/common/usbx_host_classes/src/ux_host_class_prolific_entry.c new file mode 100644 index 0000000..71e72d9 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_entry.c @@ -0,0 +1,118 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the prolific class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* prolific on the bus or when the USB prolific is removed. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* command Prolific class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_prolific_activate Activate prolific class */ +/* _ux_host_class_prolific_deactivate Deactivate prolific class */ +/* */ +/* CALLED BY */ +/* */ +/* Acm Cdc Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if(((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_PIDVID) && + (command -> ux_host_class_command_pid == 0x2303) && + (command -> ux_host_class_command_vid == 0x67b))) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_prolific_activate(command); + return(status); + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_prolific_deactivate(command); + return(status); + + default: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_ioctl.c b/common/usbx_host_classes/src/ux_host_class_prolific_ioctl.c new file mode 100644 index 0000000..6bcdb94 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_ioctl.c @@ -0,0 +1,332 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_ioctl PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the ioctl entry point for the application to */ +/* configure the Prolific device. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* prolific Pointer to prolific class */ +/* ioctl_function ioctl function */ +/* parameter pointer to structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort transfer */ +/* _ux_host_class_prolific_command Send command to device */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_long_put Put 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_ioctl(UX_HOST_CLASS_PROLIFIC *prolific, ULONG ioctl_function, + VOID *parameter) +{ + +UINT status; +UCHAR *data_buffer; +UX_HOST_CLASS_PROLIFIC_LINE_CODING *line_coding; +UX_HOST_CLASS_PROLIFIC_LINE_STATE *line_state; +ULONG value; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +VOID (*callback_function) (struct UX_HOST_CLASS_PROLIFIC_STRUCT *, ULONG ); + + /* Ensure the instance is valid. */ + if ((prolific -> ux_host_class_prolific_state != UX_HOST_CLASS_INSTANCE_LIVE) && + (prolific -> ux_host_class_prolific_state != UX_HOST_CLASS_INSTANCE_MOUNTING)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, prolific, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* The command request will tell us we need to do here. */ + switch (ioctl_function) + { + + case UX_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_CODING: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_CODING, prolific, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Allocate some cache safe memory for the control command. */ + data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PROLIFIC_LINE_CODING_LENGTH); + + /* Check if error. Return with error if no memory could be allocated. */ + if (data_buffer == UX_NULL) + + /* Do not proceed. Set error code. */ + status = UX_MEMORY_INSUFFICIENT; + else + { + + /* Build the buffer from the calling parameter. Cast the calling parameter. */ + line_coding = (UX_HOST_CLASS_PROLIFIC_LINE_CODING *) parameter; + + /* Put the data rate. */ + _ux_utility_long_put(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_RATE, + line_coding -> ux_host_class_prolific_line_coding_dter); + + /* Then the stop bit. */ + *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_STOP_BIT) = + (UCHAR) line_coding -> ux_host_class_prolific_line_coding_stop_bit; + + /* Then the parity. */ + *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_PARITY) = + (UCHAR) line_coding -> ux_host_class_prolific_line_coding_parity; + + /* Finally the data bits. */ + *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_DATA_BIT) = + (UCHAR) line_coding -> ux_host_class_prolific_line_coding_data_bits; + + /* Send the command to the device. */ + status = _ux_host_class_prolific_command(prolific, UX_HOST_CLASS_PROLIFIC_REQ_SET_LINE_CODING, + 0, data_buffer, UX_HOST_CLASS_PROLIFIC_LINE_CODING_LENGTH); + + /* We free the resources allocated no matter what. */ + _ux_utility_memory_free(data_buffer); + } + break; + + case UX_HOST_CLASS_PROLIFIC_IOCTL_GET_LINE_CODING: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_GET_LINE_CODING, prolific, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Allocate some cache safe memory for the control command. */ + data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PROLIFIC_LINE_CODING_LENGTH); + + /* Check if error. Return with error if no memory could be allocated. */ + if (data_buffer == UX_NULL) + + /* Do not proceed. Set error code. */ + status = UX_MEMORY_INSUFFICIENT; + else + { + + /* Send the command to the device. */ + status = _ux_host_class_prolific_command(prolific, UX_HOST_CLASS_PROLIFIC_REQ_GET_LINE_CODING, + 0, data_buffer, UX_HOST_CLASS_PROLIFIC_LINE_CODING_LENGTH); + + /* Fill in the calling buffer if the result is successful. */ + if (status == UX_SUCCESS) + { + + /* Build the buffer from the calling parameter. Cast the calling parameter. */ + line_coding = (UX_HOST_CLASS_PROLIFIC_LINE_CODING *) parameter; + + /* Get the data rate. */ + line_coding -> ux_host_class_prolific_line_coding_dter = _ux_utility_long_get(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_RATE); + + /* Then the stop bit. */ + line_coding -> ux_host_class_prolific_line_coding_stop_bit = + (ULONG) *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_STOP_BIT); + + /* Then the parity. */ + line_coding -> ux_host_class_prolific_line_coding_parity = + (ULONG) *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_PARITY); + + /* Finally the data bits. */ + line_coding -> ux_host_class_prolific_line_coding_data_bits = + (ULONG) *(data_buffer + UX_HOST_CLASS_PROLIFIC_LINE_CODING_DATA_BIT); + } + + /* We free the resources allocated no matter what. */ + _ux_utility_memory_free(data_buffer); + } + break; + + case UX_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_STATE: + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_SET_LINE_STATE, prolific, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Cast the calling parameter. */ + line_state = (UX_HOST_CLASS_PROLIFIC_LINE_STATE *) parameter; + + /* Build the value field. */ + value = (line_state -> ux_host_class_prolific_line_state_rts | + (line_state -> ux_host_class_prolific_line_state_dtr << 1)); + + /* Send the command to the device. */ + status = _ux_host_class_prolific_command(prolific, UX_HOST_CLASS_PROLIFIC_REQ_SET_LINE_STATE, + value, UX_NULL,0); + break; + + case UX_HOST_CLASS_PROLIFIC_IOCTL_SEND_BREAK : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_SEND_BREAK, prolific, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Build the value field. */ + value = *((ULONG *) parameter); + + /* Send the command to the device. */ + status = _ux_host_class_prolific_command(prolific, UX_HOST_CLASS_PROLIFIC_REQ_SEND_BREAK, + value, UX_NULL,0); + break; + + case UX_HOST_CLASS_PROLIFIC_IOCTL_PURGE : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_PURGE, prolific, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &prolific -> ux_host_class_prolific_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Reset upstream data pipes part 1. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PROLIFIC_VENDOR_WRITE_REQUEST; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_PROLIFIC_COMMAND_PIPE1_RESET; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Reset upstream data pipes part 1. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PROLIFIC_VENDOR_WRITE_REQUEST; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_PROLIFIC_COMMAND_PIPE2_RESET; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + break; + + case UX_HOST_CLASS_PROLIFIC_IOCTL_ABORT_IN_PIPE : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_ABORT_IN_PIPE, prolific, prolific -> ux_host_class_prolific_bulk_in_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(prolific -> ux_host_class_prolific_bulk_in_endpoint); + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_PROLIFIC_IOCTL_ABORT_OUT_PIPE : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_ABORT_OUT_PIPE, prolific, prolific -> ux_host_class_prolific_bulk_out_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to abort transactions on the bulk Out pipe. */ + _ux_host_stack_endpoint_transfer_abort(prolific -> ux_host_class_prolific_bulk_out_endpoint); + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_PROLIFIC_IOCTL_REPORT_DEVICE_STATUS_CHANGE : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_REPORT_DEVICE_STATUS_CHANGE, prolific, parameter, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Register a callback when the line state has changed. */ + callback_function = ((VOID (*) (struct UX_HOST_CLASS_PROLIFIC_STRUCT *, ULONG )) (ALIGN_TYPE)parameter); + prolific -> ux_host_class_prolific_device_status_change_callback = callback_function; + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_PROLIFIC_IOCTL_GET_DEVICE_STATUS : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_IOCTL_GET_DEVICE_STATUS, prolific, prolific -> ux_host_class_prolific_device_state, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Return the device status. */ + * ((ULONG *) parameter) = prolific -> ux_host_class_prolific_device_state; + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Function not supported. Return an error. */ + status = UX_FUNCTION_NOT_SUPPORTED; + break; + } + + /* Return status to caller. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_read.c b/common/usbx_host_classes/src/ux_host_class_prolific_read.c new file mode 100644 index 0000000..37f2a0e --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_read.c @@ -0,0 +1,191 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the prolific interface. The call is */ +/* blocking and only returns when there is either an error or when */ +/* the transfer is complete. */ +/* */ +/* INPUT */ +/* */ +/* prolific Pointer to prolific class */ +/* data_pointer Pointer to buffer */ +/* requested_length Requested data read */ +/* actual_length Actual data read */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_read (UX_HOST_CLASS_PROLIFIC *prolific, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_READ, prolific, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (prolific -> ux_host_class_prolific_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, prolific, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Start by resetting the actual length of the transfer to zero. */ + *actual_length = 0; + + /* Get the pointer to the bulk in endpoint in the transfer_request. */ + transfer_request = &prolific -> ux_host_class_prolific_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Perform a transfer on the bulk in endpoint until either the transfer is + completed or until there is an error. */ + while (requested_length) + { + + /* Program the maximum authorized length for this transfer request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer_request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PROLIFIC_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer request in case some data was actually received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked. */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion status. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + return(transfer_request -> ux_transfer_request_completion_code); + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually received and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Return success to caller. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to receive. */ + requested_length -= transfer_request_length; + } + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_reception_callback.c b/common/usbx_host_classes/src/ux_host_class_prolific_reception_callback.c new file mode 100644 index 0000000..edeff6c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_reception_callback.c @@ -0,0 +1,155 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_reception_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the callback from the USBX transfer functions, */ +/* it is called when a full or partial transfer has been done for a */ +/* bulk in transfer. It calls back the application. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_prolific_reception_callback (UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_PROLIFIC *prolific; +UX_HOST_CLASS_PROLIFIC_RECEPTION *prolific_reception; + + /* Get the class instance for this transfer request. */ + prolific = (UX_HOST_CLASS_PROLIFIC *) transfer_request -> ux_transfer_request_class_instance; + + /* Get the pointer to the prolific reception structure. */ + prolific_reception = prolific -> ux_host_class_prolific_reception; + + /* Check the state of the transfer. If there is an error, we do not proceed with this report. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* The reception is stopped. */ + prolific_reception -> ux_host_class_prolific_reception_state = UX_HOST_CLASS_PROLIFIC_RECEPTION_STATE_STOPPED; + + /* We may have an device extraction. We cannot continue. Report to the application. */ + prolific_reception -> ux_host_class_prolific_reception_callback(prolific, transfer_request -> ux_transfer_request_completion_code, UX_NULL, 0); + + + /* We do not proceed. */ + return; + + } + + /* Check if the class is in shutdown. */ + if (prolific -> ux_host_class_prolific_state == UX_HOST_CLASS_INSTANCE_SHUTDOWN) + + /* We do not proceed. */ + return; + + /* And move to the next reception buffer. Check if we are at the end of the application buffer. */ + if (prolific_reception -> ux_host_class_prolific_reception_data_head + prolific_reception -> ux_host_class_prolific_reception_block_size >= + prolific_reception -> ux_host_class_prolific_reception_data_buffer + prolific_reception -> ux_host_class_prolific_reception_data_buffer_size) + { + + /* We are at the end of the buffer. Move back to the beginning if we have space available. */ + if (prolific_reception -> ux_host_class_prolific_reception_data_tail == prolific_reception -> ux_host_class_prolific_reception_data_buffer) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_BUFFER_OVERFLOW, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We have an overflow. We cannot continue. Report to the application. */ + prolific_reception -> ux_host_class_prolific_reception_callback(prolific, UX_BUFFER_OVERFLOW, UX_NULL, 0); + + /* And stop the transfer in progress flag. */ + prolific_reception -> ux_host_class_prolific_reception_state = UX_HOST_CLASS_PROLIFIC_RECEPTION_STATE_STOPPED; + + return; + } + else + + /* Program the head to be at the beginning of the application buffer. */ + prolific_reception -> ux_host_class_prolific_reception_data_head = prolific_reception -> ux_host_class_prolific_reception_data_buffer; + + } + else + + /* Program the head to be after the current buffer. */ + prolific_reception -> ux_host_class_prolific_reception_data_head += prolific_reception -> ux_host_class_prolific_reception_block_size; + + + /* We need to report this transfer to the application. */ + prolific_reception -> ux_host_class_prolific_reception_callback(prolific, + transfer_request -> ux_transfer_request_completion_code, + transfer_request -> ux_transfer_request_data_pointer, + transfer_request -> ux_transfer_request_actual_length); + /* Update the next buffer for reception. */ + transfer_request -> ux_transfer_request_data_pointer = prolific_reception -> ux_host_class_prolific_reception_data_head; + + /* Arm another transfer. */ + _ux_host_stack_transfer_request(transfer_request); + + /* There is no status to be reported back to the stack. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_reception_start.c b/common/usbx_host_classes/src/ux_host_class_prolific_reception_start.c new file mode 100644 index 0000000..d930320 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_reception_start.c @@ -0,0 +1,128 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_reception_start PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a reception with the DLC modem. This mechanism */ +/* allows for non blocking calls based on a packet orientated round */ +/* robbin buffer. When a packet is fully or partially received, an */ +/* application callback function is invoked and a new transfer request */ +/* is rescheduled. */ +/* */ +/* INPUT */ +/* */ +/* prolific Pointer to prolific class */ +/* prolific_reception Pointer to reception struct */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_reception_start (UX_HOST_CLASS_PROLIFIC *prolific, + UX_HOST_CLASS_PROLIFIC_RECEPTION *prolific_reception) +{ + +UX_TRANSFER *transfer_request; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_RECEPTION_START, prolific, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (prolific -> ux_host_class_prolific_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, prolific, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Start by aligning the head and tail of buffers to the same address supplied by the application. */ + prolific_reception -> ux_host_class_prolific_reception_data_head = prolific_reception -> ux_host_class_prolific_reception_data_buffer; + prolific_reception -> ux_host_class_prolific_reception_data_tail = prolific_reception -> ux_host_class_prolific_reception_data_buffer; + + /* Get the pointer to the bulk in endpoint in the transfer_request. */ + transfer_request = &prolific -> ux_host_class_prolific_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Initialize the transfer request. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) prolific; + transfer_request -> ux_transfer_request_data_pointer = prolific_reception -> ux_host_class_prolific_reception_data_head; + transfer_request -> ux_transfer_request_requested_length = prolific_reception -> ux_host_class_prolific_reception_block_size; + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_prolific_reception_callback; + + /* Save the prolific reception structure in the prolific structure. */ + prolific -> ux_host_class_prolific_reception = prolific_reception; + + /* And declare we have a transfer in progress. */ + prolific_reception -> ux_host_class_prolific_reception_state = UX_HOST_CLASS_PROLIFIC_RECEPTION_STATE_STARTED; + + /* Arm a first transfer on the bulk in endpoint. There is a callback to this function so we return to the caller + right away. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* We do not know if the first transfer was successful yet. If the status is not OK, we need to stop the transfer + in progress flag. */ + if (status != UX_SUCCESS) + prolific_reception -> ux_host_class_prolific_reception_state = UX_HOST_CLASS_PROLIFIC_RECEPTION_STATE_STOPPED; + + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_reception_stop.c b/common/usbx_host_classes/src/ux_host_class_prolific_reception_stop.c new file mode 100644 index 0000000..e3bbae3 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_reception_stop.c @@ -0,0 +1,109 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_reception_stop PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a reception with a prolific device. This */ +/* mechanism allows for non blocking calls based on a packet */ +/* orientated round robbin buffer. When a packet is fully or partially */ +/* received, an application callback function is invoked and a new */ +/* transfer request is rescheduled. */ +/* */ +/* INPUT */ +/* */ +/* prolific Pointer to prolific class */ +/* prolific_reception Pointer to reception struct */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort transfer */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_reception_stop (UX_HOST_CLASS_PROLIFIC *prolific, + UX_HOST_CLASS_PROLIFIC_RECEPTION *prolific_reception) +{ + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_RECEPTION_STOP, prolific, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (prolific -> ux_host_class_prolific_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, prolific, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Check if we do have transfers for this application. If none, nothing to do. */ + if (prolific_reception -> ux_host_class_prolific_reception_state == UX_HOST_CLASS_PROLIFIC_RECEPTION_STATE_STOPPED) + return(UX_SUCCESS); + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(prolific -> ux_host_class_prolific_bulk_in_endpoint); + + /* Declare the reception stopped. */ + prolific_reception -> ux_host_class_prolific_reception_state = UX_HOST_CLASS_PROLIFIC_RECEPTION_STATE_STOPPED; + + /* This function never really fails. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_setup.c b/common/usbx_host_classes/src/ux_host_class_prolific_setup.c new file mode 100644 index 0000000..1c5e76d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_setup.c @@ -0,0 +1,416 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_setup PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the entire prolific configuration descriptors.*/ +/* This is needed because the prolific class needs to know if commands */ +/* are routed through the comm interface or the data class. */ +/* */ +/* INPUT */ +/* */ +/* prolific Pointer to prolific class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_prolific_activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_setup(UX_HOST_CLASS_PROLIFIC *prolific) +{ + +UCHAR *setup_buffer; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &prolific -> ux_host_class_prolific_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the buffer. */ + setup_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_PROLIFIC_SETUP_BUFFER_SIZE); + if (setup_buffer == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Set the device type. Can be either 0, 1 or HX. */ + if (prolific -> ux_host_class_prolific_device -> ux_device_descriptor.bDeviceClass == 0x02) + + /* Device is of type 0. */ + prolific -> ux_host_class_prolific_device_type = UX_HOST_CLASS_PROLIFIC_DEVICE_TYPE_0; + + else + { + + /* Check packet size. If 64, we are dealing with HX type device. */ + if (prolific -> ux_host_class_prolific_device -> ux_device_descriptor.bMaxPacketSize0 == 64) + + /* Device is of type HX. */ + prolific -> ux_host_class_prolific_device_type = UX_HOST_CLASS_PROLIFIC_DEVICE_TYPE_HX; + + else + + /* Default case : type 1. */ + prolific -> ux_host_class_prolific_device_type = UX_HOST_CLASS_PROLIFIC_DEVICE_TYPE_1; + + } + + /* Create a transfer request for the prolific setup request # 1. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 1; + transfer_request -> ux_transfer_request_function = 1; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_PROLIFIC_COMMAND_EEPROM_READ; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); + + } + + /* Create a transfer request for the prolific setup request # 2. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = 1; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0x0404; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); + + } + + /* Create a transfer request for the prolific setup request # 3. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 1; + transfer_request -> ux_transfer_request_function = 1; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_PROLIFIC_COMMAND_EEPROM_READ; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); + + } + + /* Create a transfer request for the prolific setup request # 4. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 1; + transfer_request -> ux_transfer_request_function = 1; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0x8383; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); + + } + + /* Create a transfer request for the prolific setup request # 5. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 1; + transfer_request -> ux_transfer_request_function = 1; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_PROLIFIC_COMMAND_EEPROM_READ; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); + + } + + /* Create a transfer request for the prolific setup request # 6. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = 1; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0x0404; + transfer_request -> ux_transfer_request_index = 1; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); + + } + + /* Create a transfer request for the prolific setup request # 7. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 1; + transfer_request -> ux_transfer_request_function = 1; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_PROLIFIC_COMMAND_EEPROM_READ; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); + + } + + /* Create a transfer request for the prolific setup request # 8. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 1; + transfer_request -> ux_transfer_request_function = 1; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0x8383; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); + + } + + /* Create a transfer request for the prolific setup request # 9. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = 1; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 1; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); + + } + + /* Create a transfer request for the prolific setup request # 9. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = 1; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = 1; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); + + } + + /* Create a transfer request for the prolific setup request # 10. */ + if (prolific -> ux_host_class_prolific_device_type == UX_HOST_CLASS_PROLIFIC_DEVICE_TYPE_HX) + + /* Chip is HX. */ + transfer_request -> ux_transfer_request_index = 0x44; + + else + + /* Chip is not HX. */ + transfer_request -> ux_transfer_request_index = 0x24; + + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = 1; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_PROLIFIC_COMMAND_REG_CONFIGURE; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + + /* Reset upstream data pipes part 1. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PROLIFIC_VENDOR_WRITE_REQUEST; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_PROLIFIC_COMMAND_PIPE1_RESET; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Reset upstream data pipes part 2. */ + transfer_request -> ux_transfer_request_data_pointer = setup_buffer; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_PROLIFIC_VENDOR_WRITE_REQUEST; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_VENDOR | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_PROLIFIC_COMMAND_PIPE2_RESET; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status, if error, do not proceed. */ + if (status != UX_SUCCESS || transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + + } + + /* Free all used resources. */ + _ux_utility_memory_free(setup_buffer); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_transfer_request_completed.c b/common/usbx_host_classes/src/ux_host_class_prolific_transfer_request_completed.c new file mode 100644 index 0000000..5bc4a72 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_transfer_request_completed.c @@ -0,0 +1,127 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** PROLIFIC Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_transfer_request_completed PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the completion thread when a transfer */ +/* request has been completed either because the transfer is */ +/* successful or there was an error. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* USBX stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_prolific_transfer_request_completed(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_PROLIFIC *prolific; + + + /* Get the class instance for this transfer request. */ + prolific = (UX_HOST_CLASS_PROLIFIC *) transfer_request -> ux_transfer_request_class_instance; + + /* Check the state of the transfer. If there is an error, we do not proceed with this notification. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + + /* We do not proceed. */ + return; + + /* Check if the class is in shutdown. */ + if (prolific -> ux_host_class_prolific_state == UX_HOST_CLASS_INSTANCE_SHUTDOWN) + + /* We do not proceed. */ + return; + + /* Increment the notification count. */ + prolific -> ux_host_class_prolific_notification_count++; + + /* Look at what the the status is. First ensure the length of our interrupt pipe data is correct. */ + if (transfer_request -> ux_transfer_request_actual_length == + prolific -> ux_host_class_prolific_interrupt_endpoint -> ux_endpoint_descriptor.wMaxPacketSize) + { + + /* Check if device is present. */ + if ((*(transfer_request -> ux_transfer_request_data_pointer + UX_HOST_CLASS_PROLIFIC_DEVICE_STATE_OFFSET) & + UX_HOST_CLASS_PROLIFIC_DEVICE_STATE_MASK) == 0) + + /* Device is not present. */ + prolific -> ux_host_class_prolific_device_state = UX_HOST_CLASS_PROLIFIC_DEVICE_NOT_PRESENT; + + else + + /* Device is present. */ + prolific -> ux_host_class_prolific_device_state = UX_HOST_CLASS_PROLIFIC_DEVICE_PRESENT; + + /* If there is a callback present, invoke it. */ + if (prolific -> ux_host_class_prolific_device_status_change_callback != UX_NULL) + + /* There is a callback, send the status change to the application. */ + prolific -> ux_host_class_prolific_device_status_change_callback(prolific, prolific -> ux_host_class_prolific_device_state); + + } + + /* Reactivate the PROLIFIC interrupt pipe. */ + _ux_host_stack_transfer_request(transfer_request); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_prolific_write.c b/common/usbx_host_classes/src/ux_host_class_prolific_write.c new file mode 100644 index 0000000..15f8bc0 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_prolific_write.c @@ -0,0 +1,190 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Prolific Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_prolific.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_prolific_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the prolific interface. The call is blocking*/ +/* and only returns when there is either an error or when the transfer */ +/* is complete. */ +/* */ +/* INPUT */ +/* */ +/* prolific Pointer to prolific class */ +/* data_pointer Pointer to data to write */ +/* requested_length Length of data to write */ +/* actual_length Actual length of data written */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_prolific_write(UX_HOST_CLASS_PROLIFIC *prolific, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_PROLIFIC_WRITE, prolific, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (prolific -> ux_host_class_prolific_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, prolific, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Start by resetting the actual length of the transfer. */ + *actual_length = 0; + + /* Get the pointer to the bulk out endpoint transfer request. */ + transfer_request = &prolific -> ux_host_class_prolific_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Perform a transfer on the bulk out endpoint until either the transfer is + completed or when there is an error. */ + while (requested_length) + { + + /* Program the maximum authorized length for this transfer_request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_PROLIFIC_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer_request in case some data actually went out. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be sent. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion status. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + return(transfer_request -> ux_transfer_request_completion_code); + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually sent and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Return success. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to send out. */ + requested_length -= transfer_request_length; + } + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_activate.c b/common/usbx_host_classes/src/ux_host_class_storage_activate.c new file mode 100644 index 0000000..d7fb0d2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_activate.c @@ -0,0 +1,168 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function activates an instance of the storage class. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_configure Configure storage device */ +/* _ux_host_class_storage_device_initialize */ +/* Initialize storage device */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy class instance */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_create Create semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_INTERFACE *interface; +UX_HOST_CLASS_STORAGE *storage; +UINT status; + + + /* The storage is always activated by the interface descriptor and not the + device descriptor. */ + interface = (UX_INTERFACE *) command -> ux_host_class_command_container; + + /* Obtain memory for this class instance. The memory used MUST BE allocated from a CACHE SAFE memory + since the buffer for the CSW is an array contained within each storage instance. */ + storage = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, sizeof(UX_HOST_CLASS_STORAGE)); + if (storage == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance */ + storage -> ux_host_class_storage_class = command -> ux_host_class_command_class_ptr; + + /* Store the interface container into the storage class instance. */ + storage -> ux_host_class_storage_interface = interface; + + /* Store the device container into the storage class instance. */ + storage -> ux_host_class_storage_device = interface -> ux_interface_configuration -> ux_configuration_device; + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(command -> ux_host_class_command_class_ptr, (VOID *) storage); + + /* This instance of the device must also be stored in the interface container. */ + interface -> ux_interface_class_instance = (VOID *) storage; + + /* Configure the USB storage device. */ + status = _ux_host_class_storage_configure(storage); + + /* Create the semaphore to protect multiple threads from accessing the same storage instance. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&storage -> ux_host_class_storage_semaphore, "ux_host_class_storage_semaphore", 1); + if (status != UX_SUCCESS) + status = UX_SEMAPHORE_ERROR; + } + + /* Error case, free resources. */ + if (status != UX_SUCCESS) + { + + /* Last one, semaphore not created or created error, no need to free. */ + + /* Error, destroy the class and return an error. */ + _ux_host_stack_class_instance_destroy(storage -> ux_host_class_storage_class, (VOID *) storage); + + /* This instance of the device must also be removed in the interface container. */ + interface -> ux_interface_class_instance = (VOID *) UX_NULL; + + /* Free memory for class instance. */ + _ux_utility_memory_free(storage); + + return(status); + } + + /* Mark the storage as mounting now. */ + storage -> ux_host_class_storage_state = UX_HOST_CLASS_INSTANCE_MOUNTING; + + /* Initialize the USB storage device. We do not check the status at this stage. We let the instance of this + class live even if there was a failure. Because the storage class has many media instance, we will let the + disconnection signal clean the instance at a later stage. */ + _ux_host_class_storage_device_initialize(storage); + + /* Mark the storage as live now. */ + storage -> ux_host_class_storage_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, storage -> ux_host_class_storage_class, (VOID *) storage); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_ACTIVATE, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, storage, 0, 0, 0) + + /* Return completion status. Force it to success. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_cbw_initialize.c b/common/usbx_host_classes/src/ux_host_class_storage_cbw_initialize.c new file mode 100644 index 0000000..3892fc3 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_cbw_initialize.c @@ -0,0 +1,111 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_cbw_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will initialize the Command Block Wrapper (CBW) that */ +/* encapsulate the SCSI request to be sent to the storage device. */ +/* The CBW is normally used only for the BO protocol. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* direction Direction of transfer */ +/* data_transfer_length Length of data transfer */ +/* command_length Length of command */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_long_put Write a 32-bit value */ +/* _ux_utility_memory_set Set memory to a value */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_storage_cbw_initialize(UX_HOST_CLASS_STORAGE *storage, UINT direction, + ULONG data_transfer_length, UINT command_length) +{ + +UCHAR *cbw; + + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Store the signature of the CBW. */ + _ux_utility_long_put(cbw, UX_HOST_CLASS_STORAGE_CBW_SIGNATURE_MASK); + + /* Set the Tag, this value is simply an arbitrary number that is echoed by + the device in the CSW. */ + _ux_utility_long_put(cbw + UX_HOST_CLASS_STORAGE_CBW_TAG, UX_HOST_CLASS_STORAGE_CBW_TAG_MASK); + + /* Store the Data Transfer Length expected for the data payload. */ + _ux_utility_long_put(cbw + UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH, data_transfer_length); + + /* Store the CBW Flag field that contains the transfer direction. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_FLAGS) = (UCHAR)direction; + + /* Store the LUN value. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_LUN) = (UCHAR)storage -> ux_host_class_storage_lun; + + /* Store the size of the SCSI command block that follows. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB_LENGTH) = (UCHAR)command_length; + + /* Reset the SCSI command block. */ + _ux_utility_memory_set(cbw + UX_HOST_CLASS_STORAGE_CBW_CB, 0, (ULONG) command_length); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_configure.c b/common/usbx_host_classes/src/ux_host_class_storage_configure.c new file mode 100644 index 0000000..62a147a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_configure.c @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to the */ +/* storage device. Once the storage is configured, its interface will */ +/* be activated. The bulk endpoints enumerated(1 IN, 1 OUT). */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get Get configuration */ +/* _ux_host_stack_device_configuration_get Get device config */ +/* _ux_host_stack_device_configuration_select Select configuration */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_configure(UX_HOST_CLASS_STORAGE *storage) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_DEVICE *parent_device; + + + /* If the device has been configured already, we don't need to do it + again. */ + if (storage -> ux_host_class_storage_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* A storage device normally has one configuration. So retrieve the 1st configuration + only. */ + status = _ux_host_stack_device_configuration_get(storage -> ux_host_class_storage_device, 0, &configuration); + + /* Check completion status. */ + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, storage -> ux_host_class_storage_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check the storage device power source and check the parent power source for + incompatible connections. */ + if (storage -> ux_host_class_storage_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* Pickup pointer to parent device. */ + parent_device = storage -> ux_host_class_storage_device -> ux_device_parent; + + /* If the device is NULL, the parent is the root hub and we don't have to worry + if the parent is not the root hub, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration. */ + status = _ux_host_stack_device_configuration_select(configuration); + if (status != UX_SUCCESS) + return(status); + + /* If the operation went well, the storage device default alternate setting + for the storage device interface is active and the interrupt endpoint is now enabled. + We have to memorize the first interface since the interrupt endpoint is hooked to it. */ + status = _ux_host_stack_configuration_interface_get(configuration, 0, 0, &storage -> ux_host_class_storage_interface); + + /* Check completion status. */ + if (status != UX_SUCCESS) + { + /* Store the instance in the interface container, this is for the USBX stack + when it needs to invoke the class. */ + storage -> ux_host_class_storage_interface -> ux_interface_class_instance = (VOID *) storage; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_deactivate.c b/common/usbx_host_classes/src/ux_host_class_storage_deactivate.c new file mode 100644 index 0000000..7ab5b0a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_deactivate.c @@ -0,0 +1,208 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the storage device */ +/* has been removed from the bus either directly or indirectly. The */ +/* bulk in\out pipes will be destroyed and the instanced removed. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* fx_media_close Close media */ +/* _ux_host_stack_endpoint_transfer_abort Abort transfer request */ +/* _ux_host_stack_class_instance_destroy Destroy class instance */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_utility_thread_schedule_other Schedule other threads */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_STORAGE *storage; +UINT media_index; +FX_MEDIA *media; +UX_HOST_CLASS_STORAGE_MEDIA *storage_media; +UX_HOST_CLASS *class; +VOID *memory; + + + /* Get the instance for this class. */ + storage = (UX_HOST_CLASS_STORAGE *) command -> ux_host_class_command_instance; + + /* We need the class container. */ + class = storage -> ux_host_class_storage_class; + + /* Point the media structure to the first media in the container. */ + storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) class -> ux_host_class_media; + + /* The storage device is being shut down. */ + storage -> ux_host_class_storage_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* We come to this point when the device has been extracted. So there may have been a transaction + being scheduled. We make sure the transaction has been completed by the controller driver. + When the device is extracted, the controller tries multiple times the transaction and retires it + with a DEVICE_NOT_RESPONDING error code. + + First we take care of endpoint OUT. */ + + /* We need to abort transactions on the bulk pipes. */ + if (storage -> ux_host_class_storage_bulk_out_endpoint != UX_NULL) + _ux_host_stack_endpoint_transfer_abort(storage -> ux_host_class_storage_bulk_out_endpoint); + + /* Then endpoint IN. */ + if (storage -> ux_host_class_storage_bulk_in_endpoint != UX_NULL) + _ux_host_stack_endpoint_transfer_abort(storage -> ux_host_class_storage_bulk_in_endpoint); + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + /* Was the protocol CBI ? */ + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_STORAGE_PROTOCOL_CBI) + { + + /* Was there an interrupt endpoint? */ + if (storage -> ux_host_class_storage_interrupt_endpoint != UX_NULL) + { + + /* Then interrupt endpoint. */ + transfer_request = &storage -> ux_host_class_storage_interrupt_endpoint -> ux_endpoint_transfer_request; + + /* Abort the data transfer on the interrupt endpoint. */ + _ux_host_stack_endpoint_transfer_abort(storage -> ux_host_class_storage_interrupt_endpoint); + + /* Free the memory that was used by the interrupt endpoint. */ + if (storage -> ux_host_class_storage_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer != UX_NULL) + _ux_utility_memory_free(storage -> ux_host_class_storage_interrupt_endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer); + } + } +#endif + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Inform FileX of the deactivation of all Media attached to this instance. */ + for (media_index = 0; media_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA; media_index++) + { + + /* Get the FileX Media attached to this media. */ + media = &storage_media -> ux_host_class_storage_media; + + /* Check if the media belongs to the device being removed. */ + if (((UX_HOST_CLASS_STORAGE *) media -> fx_media_driver_info) == storage) + { + + /* Check if the media was properly opened. */ + if (storage_media -> ux_host_class_storage_media_status == UX_HOST_CLASS_STORAGE_MEDIA_MOUNTED) + { + + /* We preserve the memory used by this media. */ + memory = storage_media -> ux_host_class_storage_media_memory; + + /* Ask FileX to unmount the partition. */ + fx_media_close(media); + + /* This device is now unmounted. */ + storage_media -> ux_host_class_storage_media_status = UX_HOST_CLASS_STORAGE_MEDIA_UNMOUNTED; + + /* Reset the media ID. */ + media -> fx_media_id = 0; + + /* Free the memory block used for data transfer on behalf of FileX. */ + _ux_utility_memory_free(memory); + } + } + + /* Move to next entry in the media array. */ + storage_media++; + } + + /* Protect thread reentry to this instance. */ + _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(storage -> ux_host_class_storage_class, (VOID *) storage); + + /* Destroy the protection semaphore. */ + _ux_utility_semaphore_delete(&storage -> ux_host_class_storage_semaphore); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, storage -> ux_host_class_storage_class, (VOID *) storage); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_DEACTIVATE, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(storage); + + /* Free the storage instance memory. */ + _ux_utility_memory_free(storage); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_device_initialize.c b/common/usbx_host_classes/src/ux_host_class_storage_device_initialize.c new file mode 100644 index 0000000..b2ddd55 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_device_initialize.c @@ -0,0 +1,169 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_device_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the USB storage device. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_device_reset Reset device */ +/* _ux_host_class_storage_device_support_check */ +/* Check protocol support */ +/* _ux_host_class_storage_endpoints_get Get all endpoints */ +/* _ux_host_class_storage_max_lun_get Get maximum number of LUNs */ +/* _ux_host_class_storage_media_characteristics_get */ +/* Get media characteristics */ +/* _ux_host_class_storage_media_format_capacity_get */ +/* Get format capacity */ +/* _ux_host_class_storage_media_mount Mount the media */ +/* _ux_utility_delay_ms Delay ms */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_device_initialize(UX_HOST_CLASS_STORAGE *storage) +{ + +UINT status; +ULONG lun_index; + + /* Check the device protocol support and initialize the transport layer. */ + status = _ux_host_class_storage_device_support_check(storage); + if (status != UX_SUCCESS) + return(status); + + /* Get the maximum number of LUN (Bulk Only device only, other device + will set the LUN number to 0). */ + status = _ux_host_class_storage_max_lun_get(storage); + if (status != UX_SUCCESS) + return(status); + + /* Search all the endpoints for the storage interface (Bulk Out, Bulk in, + and optional Interrupt endpoint). */ + status = _ux_host_class_storage_endpoints_get(storage); + if (status != UX_SUCCESS) + return(status); + + /* We need to wait for some device to settle. The INTUIX Flash disk is an example of + these device who fail the first Inquiry command if sent too quickly. + The timing does not have to be precise so we use the thread sleep function. + The default sleep value is 2 seconds. */ + _ux_utility_delay_ms(UX_HOST_CLASS_STORAGE_DEVICE_INIT_DELAY); + + /* Each LUN must be parsed and mounted. */ + for (lun_index = 0; lun_index <= storage -> ux_host_class_storage_max_lun; lun_index++) + { + + /* Set the LUN into the storage instance. */ + storage -> ux_host_class_storage_lun = lun_index; + + /* Get the media type supported by this storage device. */ + status = _ux_host_class_storage_media_characteristics_get(storage); + if (status == UX_HOST_CLASS_MEDIA_NOT_SUPPORTED) + { + /* Unsupported device. */ + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEDIA_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_MEDIA_NOT_SUPPORTED, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) + + continue; + } + if (status != UX_SUCCESS) + return(status); + + /* Get the format capacity of this storage device. */ + status = _ux_host_class_storage_media_format_capacity_get(storage); + if (status != UX_SUCCESS) + return(status); + + /* Store the LUN type in the LUN type array. */ + storage -> ux_host_class_storage_lun_types[lun_index] = storage -> ux_host_class_storage_media_type; + + /* Check the media type. We support regular FAT drives and optical drives. + No CD-ROM support in this release. */ + switch (storage -> ux_host_class_storage_media_type) + { + + case UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK: + case UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK: + case UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK: + + /* Try to read the device media in search for a partition table or boot sector. + We are at the root of the disk, so use sector 0 as the starting point. */ + _ux_host_class_storage_media_mount(storage, 0); + break; + + case UX_HOST_CLASS_STORAGE_MEDIA_CDROM: + default: + + /* In the case of CD-ROM, we do no need to mount any file system yet. The application + can read sectors directly. */ + + break; + } + } + + /* Some LUNs may succeed and some may fail. For simplicity's sake, we just + return success. The storage thread will try to remount the ones that failed. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_device_reset.c b/common/usbx_host_classes/src/ux_host_class_storage_device_reset.c new file mode 100644 index 0000000..1551a73 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_device_reset.c @@ -0,0 +1,117 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_device_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will perform a reset on the device if it is a */ +/* Bulk Only device. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_endpoint_reset Reset endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_device_reset(UX_HOST_CLASS_STORAGE *storage) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; + + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + /* We need to perform a reset only for BO devices. */ + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_STORAGE_PROTOCOL_BO) + { +#endif + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &storage -> ux_host_class_storage_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* We need to prevent other threads from simultaneously using the endpoint. */ + _ux_utility_semaphore_get(&control_endpoint -> ux_endpoint_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Create a transfer_request for the RESET request. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_STORAGE_RESET; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Per the spec, reset the endpoints as well. */ + _ux_host_stack_endpoint_reset(storage -> ux_host_class_storage_bulk_in_endpoint); + _ux_host_stack_endpoint_reset(storage -> ux_host_class_storage_bulk_out_endpoint); + + /* Return completion status. */ + return(status); + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + } + + /* In case the device is not a BO device, we always succeed. */ + return(UX_SUCCESS); +#endif +} diff --git a/common/usbx_host_classes/src/ux_host_class_storage_device_support_check.c b/common/usbx_host_classes/src/ux_host_class_storage_device_support_check.c new file mode 100644 index 0000000..0f95bf4 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_device_support_check.c @@ -0,0 +1,137 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_device_support_check PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function verifies the support for the subclass and protocol */ +/* of the USB device. If the device is supported it will update the */ +/* storage class instances with the transport layer functions. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_device_support_check(UX_HOST_CLASS_STORAGE *storage) +{ + + /* Check for the protocol type (BO/CB/CBI) and update the transport functions. */ + switch(storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol) + { + + case UX_HOST_CLASS_STORAGE_PROTOCOL_BO: + + storage -> ux_host_class_storage_transport = _ux_host_class_storage_transport_bo; + break; + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + case UX_HOST_CLASS_STORAGE_PROTOCOL_CB: + + storage -> ux_host_class_storage_transport = _ux_host_class_storage_transport_cb; + break; + + + case UX_HOST_CLASS_STORAGE_PROTOCOL_CBI: + + /* In case of CBI, the subclass must be UFI, if not, default back to CB transport. */ + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + storage -> ux_host_class_storage_transport = _ux_host_class_storage_transport_cbi; + else + storage -> ux_host_class_storage_transport = _ux_host_class_storage_transport_cb; + break; +#endif + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_PROTOCOL_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_PROTOCOL_ERROR, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_PROTOCOL_ERROR); + } + + /* Check for the sub class and make sure we support it. */ + switch (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass) + { + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + case UX_HOST_CLASS_STORAGE_SUBCLASS_UFI: +#endif + case UX_HOST_CLASS_STORAGE_SUBCLASS_RBC: + case UX_HOST_CLASS_STORAGE_SUBCLASS_SCSI: + case UX_HOST_CLASS_STORAGE_SUBCLASS_SFF8020: + case UX_HOST_CLASS_STORAGE_SUBCLASS_SFF8070: + + return(UX_SUCCESS); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_PROTOCOL_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_PROTOCOL_ERROR, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_PROTOCOL_ERROR); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_driver_entry.c b/common/usbx_host_classes/src/ux_host_class_storage_driver_entry.c new file mode 100644 index 0000000..aa478d2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_driver_entry.c @@ -0,0 +1,214 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_driver_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point for the FileX file system. All */ +/* FileX driver I/O calls are are multiplexed here and rerouted to */ +/* the proper USB storage class functions. */ +/* */ +/* INPUT */ +/* */ +/* media FileX media pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_sense_code_translate */ +/* Translate error status codes */ +/* _ux_host_class_storage_media_read Read sector(s) */ +/* _ux_host_class_storage_media_write Write sector(s) */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* FileX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_storage_driver_entry(FX_MEDIA *media) +{ + +UINT status; +UX_HOST_CLASS_STORAGE *storage; +UX_HOST_CLASS_STORAGE_MEDIA *storage_media; + + + /* Get the pointer to the storage instance. */ + storage = (UX_HOST_CLASS_STORAGE *) media -> fx_media_driver_info; + + /* Get the pointer to the media instance. */ + storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) media -> fx_media_reserved_for_user; + + /* Ensure the instance is valid. */ + if ((storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_LIVE) && + (storage -> ux_host_class_storage_state != UX_HOST_CLASS_INSTANCE_MOUNTING)) + { + + /* Class instance is invalid. Return an error! */ + media -> fx_media_driver_status = FX_PTR_ERROR; + return; + } + + /* Protect Thread reentry to this instance. */ + _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + + /* Restore the LUN number from the media instance. */ + storage -> ux_host_class_storage_lun = storage_media -> ux_host_class_storage_media_lun; + + /* And the sector size. */ + storage -> ux_host_class_storage_sector_size = storage_media -> ux_host_class_storage_media_sector_size; + + + /* Look at the request specified by the FileX caller. */ + switch (media -> fx_media_driver_request) + { + + case FX_DRIVER_READ: + + /* Read one or more sectors. */ + status = _ux_host_class_storage_media_read(storage, media -> fx_media_driver_logical_sector + + storage_media -> ux_host_class_storage_media_partition_start, + media -> fx_media_driver_sectors, media -> fx_media_driver_buffer); + + /* Check completion status. */ + if (status == UX_SUCCESS) + media -> fx_media_driver_status = FX_SUCCESS; + else + media -> fx_media_driver_status = _ux_host_class_storage_sense_code_translate(storage, status); + break; + + + case FX_DRIVER_WRITE: + + /* Write one or more sectors. */ + status = _ux_host_class_storage_media_write(storage, media -> fx_media_driver_logical_sector + + storage_media -> ux_host_class_storage_media_partition_start, + media -> fx_media_driver_sectors, media -> fx_media_driver_buffer); + + /* Check completion status. */ + if (status == UX_SUCCESS) + media -> fx_media_driver_status = FX_SUCCESS; + else + media -> fx_media_driver_status = _ux_host_class_storage_sense_code_translate(storage,status); + break; + + + case FX_DRIVER_FLUSH: + + /* Nothing to do. Just return a good status! */ + media -> fx_media_driver_status = FX_SUCCESS; + break; + + case FX_DRIVER_ABORT: + + /* Nothing to do. Just return a good status! */ + media -> fx_media_driver_status = FX_SUCCESS; + break; + + case FX_DRIVER_INIT: + + /* Check for media protection. We must do this operation here because FileX clears all the + media fields before init. */ + if (storage -> ux_host_class_storage_write_protected_media == UX_TRUE) + + /* The media is Write Protected. We tell FileX. */ + media -> fx_media_driver_write_protect = UX_TRUE; + + /* This function always succeeds. */ + media -> fx_media_driver_status = FX_SUCCESS; + break; + + + case FX_DRIVER_UNINIT: + + /* Nothing to do. Just return a good status! */ + media -> fx_media_driver_status = FX_SUCCESS; + break; + + + case FX_DRIVER_BOOT_READ: + + /* Read the media boot sector. */ + status = _ux_host_class_storage_media_read(storage, storage_media -> ux_host_class_storage_media_partition_start, 1, + media -> fx_media_driver_buffer); + + /* Check completion status. */ + if (status == UX_SUCCESS) + media -> fx_media_driver_status = FX_SUCCESS; + else + media -> fx_media_driver_status = _ux_host_class_storage_sense_code_translate(storage,status); + break; + + + case FX_DRIVER_BOOT_WRITE: + + /* Write the boot sector. */ + status = _ux_host_class_storage_media_write(storage, storage_media -> ux_host_class_storage_media_partition_start, 1, + media -> fx_media_driver_buffer); + + /* Check completion status. */ + if (status == UX_SUCCESS) + media -> fx_media_driver_status = FX_SUCCESS; + else + media -> fx_media_driver_status = _ux_host_class_storage_sense_code_translate(storage, status); + break; + + default: + + /* Invalid request from FileX */ + media -> fx_media_driver_status = FX_IO_ERROR; + break; + } + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); +} diff --git a/common/usbx_host_classes/src/ux_host_class_storage_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_storage_endpoints_get.c new file mode 100644 index 0000000..0224a89 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_endpoints_get.c @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function searches for the handle of the bulk out endpoint and */ +/* optionally the bulk in endpoint. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_endpoint_get Get an endpoint pointer */ +/* _ux_utility_memory_allocate Allocate memory */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_endpoints_get(UX_HOST_CLASS_STORAGE *storage) +{ + +UINT endpoint_index; +UX_ENDPOINT *endpoint; + + + /* Search for the bulk OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get an endpoint. */ + _ux_host_stack_interface_endpoint_get(storage -> ux_host_class_storage_interface, endpoint_index, &endpoint); + + /* We have an endpoint. Check if endpoint is bulk and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* We have found the bulk OUT endpoint, save it! */ + storage -> ux_host_class_storage_bulk_out_endpoint = endpoint; + + /* This transfer request always has the OUT direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + + break; + } + } + + /* The bulk OUT endpoint is mandatory. */ + if (storage -> ux_host_class_storage_bulk_out_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search for the bulk IN endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get an endpoint. */ + _ux_host_stack_interface_endpoint_get(storage -> ux_host_class_storage_interface, endpoint_index, &endpoint); + + /* We have an endpoint. Check if endpoint is bulk and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* We have found the bulk IN endpoint, save it! */ + storage -> ux_host_class_storage_bulk_in_endpoint = endpoint; + + /* This transfer request always has the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + break; + } + } + + /* The bulk IN endpoint is mandatory */ + if (storage -> ux_host_class_storage_bulk_in_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + /* Search the Interrupt IN endpoint. This endpoint is optional and only valid for + storage devices that use the CBI protocol. */ + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_STORAGE_PROTOCOL_CBI) + { + + /* Yes, CBI protocol is present. Search for Interrupt IN endpoint. */ + for (endpoint_index = 0; endpoint_index < storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get an endpoint. */ + _ux_host_stack_interface_endpoint_get(storage -> ux_host_class_storage_interface, endpoint_index, &endpoint); + + /* Check if endpoint is Interrupt and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_INTERRUPT_ENDPOINT)) + { + + /* We have found the Interrupt IN endpoint, save it! */ + storage -> ux_host_class_storage_interrupt_endpoint = endpoint; + + /* This transfer request always has the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* The size of the transfer is fixed to the endpoint size. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_requested_length = + endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + + /* Get some memory for this data transfer. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer = + _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, + endpoint -> ux_endpoint_descriptor.wMaxPacketSize); + + /* Check the memory pointer. */ + if (endpoint -> ux_endpoint_transfer_request.ux_transfer_request_data_pointer == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + break; + } + } + + if (storage -> ux_host_class_storage_interrupt_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + } +#endif + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_entry.c b/common/usbx_host_classes/src/ux_host_class_storage_entry.c new file mode 100644 index 0000000..863c292 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_entry.c @@ -0,0 +1,185 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + +UX_COMPILE_TIME_ASSERT(!UX_OVERFLOW_CHECK_MULC_ULONG(sizeof(UX_HOST_CLASS_STORAGE_MEDIA), UX_HOST_CLASS_STORAGE_MAX_MEDIA), UX_HOST_CLASS_STORAGE_MAX_MEDIA_mul_ovf) + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the storage class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* USB disk on the bus or when the USB disk is removed. */ +/* */ +/* Version 2.0 of the storage class only supports USB FAT media and */ +/* not CD-ROM. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_activate Activate storage class */ +/* _ux_host_class_storage_deactivate Deactivate storage class */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_thread_create Create storage class thread */ +/* */ +/* CALLED BY */ +/* */ +/* Host Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if ((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) && + (command -> ux_host_class_command_class == UX_HOST_CLASS_STORAGE_CLASS)) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* We are assuming the device will mount. If this is the first activation of + the storage class, we have to fire up one thread for the media insertion + and acquire some memory for the media array. */ + + /* Allocate some memory for the media structures used by FileX. */ + if (command -> ux_host_class_command_class_ptr -> ux_host_class_media == UX_NULL) + { + + /* UX_HOST_CLASS_STORAGE_MAX_MEDIA*sizeof(UX_HOST_CLASS_STORAGE_MEDIA) overflow + * is checked outside of function. + */ + command -> ux_host_class_command_class_ptr -> ux_host_class_media = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_HOST_CLASS_STORAGE_MAX_MEDIA*sizeof(UX_HOST_CLASS_STORAGE_MEDIA)); + + /* Check the completion status. */ + if (command -> ux_host_class_command_class_ptr -> ux_host_class_media == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + } + + /* Allocate a Thread stack and create the thread. */ + if (command -> ux_host_class_command_class_ptr -> ux_host_class_thread_stack == UX_NULL) + { + + /* Allocate a Thread stack. */ + command -> ux_host_class_command_class_ptr -> ux_host_class_thread_stack = + _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE); + + /* Check the completion status. */ + if (command -> ux_host_class_command_class_ptr -> ux_host_class_thread_stack == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Create the storage class thread. */ + status = _ux_utility_thread_create(&command -> ux_host_class_command_class_ptr -> ux_host_class_thread, + "ux_host_storage_thread", _ux_host_class_storage_thread_entry, + (ULONG) (ALIGN_TYPE) command -> ux_host_class_command_class_ptr, + command -> ux_host_class_command_class_ptr -> ux_host_class_thread_stack, + UX_HOST_CLASS_STORAGE_THREAD_STACK_SIZE, + UX_HOST_CLASS_STORAGE_THREAD_PRIORITY_CLASS, + UX_HOST_CLASS_STORAGE_THREAD_PRIORITY_CLASS, + TX_NO_TIME_SLICE, TX_DONT_START); + + /* Check the completion status. */ + if (status != UX_SUCCESS) + { + _ux_utility_memory_free(command -> ux_host_class_command_class_ptr -> ux_host_class_thread_stack); + command -> ux_host_class_command_class_ptr -> ux_host_class_thread_stack = UX_NULL; + return(UX_THREAD_ERROR); + } + + UX_THREAD_EXTENSION_PTR_SET(&(command -> ux_host_class_command_class_ptr -> ux_host_class_thread), command -> ux_host_class_command_class_ptr) + + /* Now that the extension pointer has been set, resume the thread. */ + tx_thread_resume(&command -> ux_host_class_command_class_ptr -> ux_host_class_thread); + } + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_storage_activate(command); + + /* Return the completion status. */ + return(status); + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_storage_deactivate(command); + + /* Return the completion status. */ + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return an error. */ + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_max_lun_get.c b/common/usbx_host_classes/src/ux_host_class_storage_max_lun_get.c new file mode 100644 index 0000000..0a6542d --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_max_lun_get.c @@ -0,0 +1,147 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_max_lun_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function retrieves the maximum number of LUNs from the device. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_max_lun_get(UX_HOST_CLASS_STORAGE *storage) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +UCHAR *storage_data_buffer; + + + /* In the case of non BO device or an error on the command the number of lun should be + set to 0, indicating 1 lun. */ + storage -> ux_host_class_storage_max_lun = 0; + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + /* Check the device type. */ + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_STORAGE_PROTOCOL_BO) + { +#endif + + /* We need to get the default control endpoint transfer_request pointer. */ + control_endpoint = &storage -> ux_host_class_storage_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* We need to prevent other threads from simultaneously using the control endpoint. */ + _ux_utility_semaphore_get(&control_endpoint -> ux_endpoint_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Need to allocate memory for the descriptor. */ + storage_data_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 1); + if (storage_data_buffer == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Create a transfer_request for the GET_MAX_LUN request. */ + transfer_request -> ux_transfer_request_data_pointer = storage_data_buffer; + transfer_request -> ux_transfer_request_requested_length = 1; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_STORAGE_GET_MAX_LUN; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 1)) + { + + /* Retrieve the number of max LUN for this device. */ + storage -> ux_host_class_storage_max_lun = *storage_data_buffer; + + /* Is the max LUN index greater than our LUN array's? */ + if (storage -> ux_host_class_storage_max_lun > UX_MAX_HOST_LUN - 1) + { + + /* Cap it off. */ + storage -> ux_host_class_storage_max_lun = UX_MAX_HOST_LUN - 1; + + /* Notify application so it knows to increase UX_MAX_HOST_LUN. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEMORY_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_MEMORY_ERROR, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) + } + } + + /* Free all used resources. */ + _ux_utility_memory_free(storage_data_buffer); + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + } +#endif + + /* We always succeed. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_capacity_get.c b/common/usbx_host_classes/src/ux_host_class_storage_media_capacity_get.c new file mode 100644 index 0000000..d58848c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_capacity_get.c @@ -0,0 +1,180 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_media_capacity_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will send a READ_CAPACITY command to the storage */ +/* device. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_cbw_initialize Initialize CBW */ +/* _ux_host_class_storage_transport Send command */ +/* _ux_host_class_storage_media_format_capacity_get */ +/* Get format capacity */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_long_get_big_endian Get 32-bit big endian */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_media_capacity_get(UX_HOST_CLASS_STORAGE *storage) +{ + +UINT status; +UCHAR *cbw; +UCHAR *capacity_response; +UINT command_length; +ULONG command_retry; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_CAPACITY_GET, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Set the default to either 512 or 2048 bytes. */ + switch (storage -> ux_host_class_storage_media_type) + { + + case UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK: + case UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK: + + storage -> ux_host_class_storage_sector_size = UX_HOST_CLASS_STORAGE_SECTOR_SIZE_FAT; + break; + + case UX_HOST_CLASS_STORAGE_MEDIA_CDROM: + case UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK: + + storage -> ux_host_class_storage_sector_size = UX_HOST_CLASS_STORAGE_SECTOR_SIZE_OTHER; + break; + + default: + + /* Unsupported device. */ + return(UX_HOST_CLASS_MEDIA_NOT_SUPPORTED); + } + + /* First, we test if the device is ready. Then try to read its capacity. + On floppies, this operation tends to fail a few times. So we try harder. */ + for (command_retry = 0; command_retry < UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY; command_retry++) + { + + /* Some devices require we do this. */ + status = _ux_host_class_storage_media_format_capacity_get(storage); + if (status != UX_SUCCESS) + return(status); + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Get the READ_CAPACITY command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_READ_CAPACITY_COMMAND_LENGTH_SBC; +#endif + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_IN, UX_HOST_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH, command_length); + + /* Prepare the READ_CAPACITY command block. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_READ_CAPACITY_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_READ_CAPACITY; + + /* Obtain a block of memory for the answer. */ + capacity_response = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_READ_CAPACITY_RESPONSE_LENGTH); + if (capacity_response == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Send the command to transport layer. */ + status = _ux_host_class_storage_transport(storage, capacity_response); + + /* Check for error during transfer. */ + if (status != UX_SUCCESS) + { + + /* Free the memory resource used for the command response. */ + _ux_utility_memory_free(capacity_response); + + /* We return a sad status. */ + return(status); + } + + /* Check the sense code */ + if (storage -> ux_host_class_storage_sense_code == UX_SUCCESS) + { + + /* The data is valid, save the sector size. */ + storage -> ux_host_class_storage_sector_size = _ux_utility_long_get_big_endian(capacity_response + UX_HOST_CLASS_STORAGE_READ_CAPACITY_DATA_SECTOR_SIZE); + + /* Free the memory resource used for the command response. */ + _ux_utility_memory_free(capacity_response); + + /* We return a happy status. */ + return(UX_SUCCESS); + } + + /* Free the memory resource used for the command response. */ + _ux_utility_memory_free(capacity_response); + } + + /* We get here when we could not retrieve the sector size through the READ_CAPACITY command. + It's OK, we still calculated the default based on the device type. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_characteristics_get.c b/common/usbx_host_classes/src/ux_host_class_storage_media_characteristics_get.c new file mode 100644 index 0000000..3d5975a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_characteristics_get.c @@ -0,0 +1,134 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_media_characteristics_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will send a INQUIRY command to get the type of */ +/* device/media we are dealing with. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_cbw_initialize Initialize CBW */ +/* _ux_host_class_storage_transport Send command */ +/* _ux_host_class_storage_media_capacity_get */ +/* Get media capacity */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_media_characteristics_get(UX_HOST_CLASS_STORAGE *storage) +{ + +UINT status; +UCHAR *cbw; +UCHAR *inquiry_response; +UINT command_length; + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Get the Write Command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_INQUIRY_COMMAND_LENGTH_SBC; +#endif + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_IN, UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH, command_length); + + /* Prepare the INQUIRY command block. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_INQUIRY_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_INQUIRY; + + /* Store the length of the Inquiry Response. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_INQUIRY_ALLOCATION_LENGTH) = UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH; + + /* Obtain a block of memory for the answer. */ + inquiry_response = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_LENGTH); + if (inquiry_response == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Send the command to transport layer. */ + status = _ux_host_class_storage_transport(storage, inquiry_response); + + /* If we have a transport error, there is not much we can do, simply return the + error. */ + if (status == UX_SUCCESS) + { + + /* The Inquiry response contains the type of device/media and a media removable flag. */ + storage -> ux_host_class_storage_media_type = *(inquiry_response + UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_PERIPHERAL_TYPE); + storage -> ux_host_class_storage_lun_removable_media_flags[storage -> ux_host_class_storage_lun] = *(inquiry_response + UX_HOST_CLASS_STORAGE_INQUIRY_RESPONSE_REMOVABLE_MEDIA); + + /* Attempt to read the device capacity in order to retrieve the Sector Size. If the command fails, + we will default to 512 bytes for a regular drive and 2048 bytes for a CD-ROM or optical drive. */ + status = _ux_host_class_storage_media_capacity_get(storage); + } + + /* Free the memory resource used for the command response. */ + _ux_utility_memory_free(inquiry_response); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_format_capacity_get.c b/common/usbx_host_classes/src/ux_host_class_storage_media_format_capacity_get.c new file mode 100644 index 0000000..959cc45 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_format_capacity_get.c @@ -0,0 +1,122 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_media_format_capacity_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will send a READ_FORMAT_CAPACITY command to the */ +/* device. Some USB storage disk require this function for the sanity */ +/* of their state machine. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_cbw_initialize Initialize CBW */ +/* _ux_host_class_storage_transport Send command */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_short_put_big_endian Put 32-bit big endian */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_media_format_capacity_get(UX_HOST_CLASS_STORAGE *storage) +{ + +UCHAR *cbw; +UCHAR *read_format_capacity_response; +UINT command_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_FORMAT_CAPACITY_GET, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Get the Write Command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_READ_FORMAT_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_READ_FORMAT_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_READ_FORMAT_COMMAND_LENGTH_SBC; +#endif + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_IN, UX_HOST_CLASS_STORAGE_READ_FORMAT_RESPONSE_LENGTH, command_length); + + /* Prepare the READ FORMAT CAPACITY command block. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_READ_FORMAT_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_READ_FORMAT_CAPACITY; + + /* Store the number of sectors to read. */ + _ux_utility_short_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_READ_FORMAT_PARAMETER_LIST_LENGTH, UX_HOST_CLASS_STORAGE_READ_FORMAT_RESPONSE_LENGTH); + + /* Obtain a block of memory for the answer. */ + read_format_capacity_response = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_READ_FORMAT_RESPONSE_LENGTH); + if (read_format_capacity_response == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Send the command to transport layer. */ + _ux_host_class_storage_transport(storage, read_format_capacity_response); + + /* Free the memory resource used for the command response. */ + _ux_utility_memory_free(read_format_capacity_response); + + /* If we have a transport error, there is not much we can do, we do not fail. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_mount.c b/common/usbx_host_classes/src/ux_host_class_storage_media_mount.c new file mode 100644 index 0000000..3b56772 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_mount.c @@ -0,0 +1,190 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_media_mount PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function tries to read the first sector on the media. It then */ +/* determines if this is a partition sector or a boot sector. If the */ +/* sector contains partition information, each partition is checked */ +/* for a DOS aware partition and mounted by FileX. */ +/* */ +/* If there is no partition sector or boot sector, we simply inform */ +/* FileX that a device is present and that its boot sector should be */ +/* periodically read to see if the device is mounted. This mechanism */ +/* applies to storage where the media can be removed (floppy, ZIP, */ +/* flash/smart media readers). */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* sector Boot sector start */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_media_mount Mount media */ +/* _ux_host_class_storage_media_open Open media */ +/* _ux_host_class_storage_partition_read Read partition */ +/* _ux_host_class_storage_media_read Read sectors of media */ +/* _ux_host_class_storage_start_stop Start the media */ +/* _ux_host_class_storage_unit_ready_test */ +/* Test unit ready */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_short_get Get 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_media_mount(UX_HOST_CLASS_STORAGE *storage, ULONG sector) +{ + +UCHAR *sector_memory; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_MOUNT, storage, sector, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + /* If the device is UFI, we need to start it. */ + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol == UX_HOST_CLASS_STORAGE_PROTOCOL_CBI) + { + + /* Start the media. */ + status = _ux_host_class_storage_start_stop(storage, UX_HOST_CLASS_STORAGE_START_MEDIA); + + /* Check the status. If the device does not start, fail the operation. + But we still return SUCCESS otherwise the storage thread has no chance to inspect this instance. */ + if (status != UX_SUCCESS) + return(UX_SUCCESS); + } +#endif + + /* Obtain memory for reading the partition sector, we do not use the storage instance + memory because this function is reentrant. */ + sector_memory = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, storage -> ux_host_class_storage_sector_size); + if (sector_memory == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Check if the device is now ready. */ + status = _ux_host_class_storage_unit_ready_test(storage); + + /* Check the status. There may be a transport error or the device is not ready. */ + if (status == UX_SUCCESS) + + /* Read the very first sector from the media. */ + status = _ux_host_class_storage_media_read(storage, sector, 1, sector_memory); + + /* Check the status. There may be a transport error or the device is not ready. */ + if (status != UX_SUCCESS) + { + + /* In any case, we free the sector memory. */ + _ux_utility_memory_free(sector_memory); + + if (status == UX_HOST_CLASS_STORAGE_SENSE_ERROR) + + /* The media is not there, so we will try to check for it at the storage + thread level every x seconds. */ + return(UX_SUCCESS); + + /* Since there was a transport error or command error, we do not try to mount + a fake media. */ + return(status); + } + + /* We need to examine this sector and determine if this is a partition sector + or a boot sector. */ + if (_ux_utility_short_get(sector_memory + 510) == UX_HOST_CLASS_STORAGE_PARTITION_SIGNATURE) + { + + /* If we have a signature, we know it is a valid media and it may be formatted. + If there is no signature, the media exist but maybe not formatted. Now determine + if this is a boot sector. The boot sector has a special signature in the first + couple of bytes. + BUT !!! The first boot sector of an iPod is actually a partition, so we need to + look further and see if the number of sector per FAT and the first partition are + set to 0. This will indicate a partition sector. + */ + if ((*sector_memory == 0xe9) || ((*sector_memory == 0xeb) && *(sector_memory + 2) == 0x90)) + { + + /* Check for fake boot sector. */ + if (_ux_utility_short_get(sector_memory + 0x16) != 0x0 || _ux_utility_long_get(sector_memory + 0x24) != 0x0) + { + + /* This is a boot sector signature. */ + _ux_host_class_storage_media_open(storage, sector); + _ux_utility_memory_free(sector_memory); + return(UX_SUCCESS); + } + } + + _ux_host_class_storage_partition_read(storage, sector_memory, sector); + _ux_utility_memory_free(sector_memory); + return(UX_SUCCESS); + } + else + { + + /* The drive does not contain a partition table or FAT MBR at LBA 0*/ + status = UX_ERROR; + } + + /* Free all resources used. */ + _ux_utility_memory_free(sector_memory); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_open.c b/common/usbx_host_classes/src/ux_host_class_storage_media_open.c new file mode 100644 index 0000000..9f9f963 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_open.c @@ -0,0 +1,162 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_media_open PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will ask FileX to mount a new partition for this */ +/* device. This function has some FileX dependencies. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* hidden_sectors Number of hidden sectors */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* fx_media_open Media open */ +/* _ux_host_class_storage_media_protection_check */ +/* Check for protection */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_storage_media_mount Media open */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_media_open(UX_HOST_CLASS_STORAGE *storage, ULONG hidden_sectors) +{ + +UINT status; +UINT media_index; +UX_HOST_CLASS_STORAGE_MEDIA *storage_media; +FX_MEDIA *media; +UX_HOST_CLASS *class; + + + /* We need the class container. */ + class = storage -> ux_host_class_storage_class; + + /* Point the media structure to the first media in the container. */ + storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) class -> ux_host_class_media; + + /* Locate a free partition in the storage instance. */ + for (media_index = 0; media_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA; media_index++) + { + + /* Get the FileX media pointer for that media. */ + media = &storage_media -> ux_host_class_storage_media; + + /* Is the media valid? */ + if (media -> fx_media_id == 0) + { + + /* Save the storage instance in the media instance. */ + media -> fx_media_driver_info = (VOID *) storage; + + /* Save the number of hidden sectors in this partition. */ + storage_media -> ux_host_class_storage_media_partition_start = hidden_sectors; + + /* Save the LUN number in the storage media instance. */ + storage_media -> ux_host_class_storage_media_lun = storage -> ux_host_class_storage_lun; + + /* Save the Sector size in the storage media instance. */ + storage_media -> ux_host_class_storage_media_sector_size = storage -> ux_host_class_storage_sector_size; + + /* Save the storage media instance in the user reserved area in the FX_MEDIA structure. */ + media -> fx_media_reserved_for_user = (ALIGN_TYPE) storage_media; + + /* We now need to allocate a block of memory for FileX to use when doing transfers + The default buffer size is 8K. The value used for the definition is UX_HOST_CLASS_STORAGE_MEMORY_BUFFER_SIZE. + This value can be changed to save on memory space but should not be smaller than + the media sector size (which should be 512 bytes). Because USB devices are SCSI + devices and there is a great deal of overhead when doing read/writes, it is better + to leave the default buffer size or even increase it. */ + storage_media -> ux_host_class_storage_media_memory = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_MEMORY_BUFFER_SIZE); + if (storage_media -> ux_host_class_storage_media_memory == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_OPEN, storage, media, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ask FileX to mount the partition. */ + status = fx_media_open(media, UX_HOST_CLASS_STORAGE_MEDIA_NAME, _ux_host_class_storage_driver_entry, + storage, storage_media -> ux_host_class_storage_media_memory, + UX_HOST_CLASS_STORAGE_MEMORY_BUFFER_SIZE); + + /* If the media is mounted, update the status for the application. */ + if (status == UX_SUCCESS) + storage_media -> ux_host_class_storage_media_status = UX_HOST_CLASS_STORAGE_MEDIA_MOUNTED; + + else + + /* Free the memory resources. */ + _ux_utility_memory_free(storage_media -> ux_host_class_storage_media_memory); + + /* Return completion status. */ + return(status); + } + + /* Move to next entry in the media array. */ + storage_media++; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_MEMORY_ERROR); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_MEMORY_ERROR, storage, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Return error. */ + return(UX_HOST_CLASS_MEMORY_ERROR); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_protection_check.c b/common/usbx_host_classes/src/ux_host_class_storage_media_protection_check.c new file mode 100644 index 0000000..f24d91a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_protection_check.c @@ -0,0 +1,160 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_media_protection_check PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will send a MODE_SENSE command to retrieve the medium */ +/* and device parameters. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_cbw_initialize Initialize CBW */ +/* _ux_host_class_storage_transport Send command */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_short_get_big_endian Get short value */ +/* _ux_utility_short_put_big_endian Put short value */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_media_protection_check(UX_HOST_CLASS_STORAGE *storage) +{ + +UINT status; +UCHAR *cbw; +UCHAR *mode_sense_response; +UINT command_length; +ULONG wp_parameter_location; + + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Get the Write Command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_SBC; +#endif + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_IN, UX_HOST_CLASS_STORAGE_MODE_SENSE_ALL_PAGE_LENGTH, command_length); + + /* Prepare the MODE_SENSE command block. Distinguish between SUBCLASSES. */ + switch (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass) + { + + case UX_HOST_CLASS_STORAGE_SUBCLASS_RBC : +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + case UX_HOST_CLASS_STORAGE_SUBCLASS_UFI : +#endif + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_MODE_SENSE_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_MODE_SENSE; + wp_parameter_location = UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_ATTRIBUTES; + break; + + default : + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_MODE_SENSE_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT; + wp_parameter_location = UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_ATTRIBUTES_SHORT; + break; + } + + /* We ask for all pages. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_MODE_SENSE_PC_PAGE_CODE) = UX_HOST_CLASS_STORAGE_MODE_SENSE_ALL_PAGE; + + /* Store the length of the Inquiry Response. */ + _ux_utility_short_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_MODE_SENSE_PARAMETER_LIST_LENGTH, UX_HOST_CLASS_STORAGE_MODE_SENSE_ALL_PAGE_LENGTH); + + /* Obtain a block of memory for the answer. */ + mode_sense_response = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_MODE_SENSE_ALL_PAGE_LENGTH); + if (mode_sense_response == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Send the command to transport layer. */ + status = _ux_host_class_storage_transport(storage, mode_sense_response); + + /* Reset the Write Protected flag. */ + storage -> ux_host_class_storage_write_protected_media = UX_FALSE; + + /* If we have a transport error, there is not much we can do, simply return the + error. The default will be non protected disk. */ + if (status == UX_SUCCESS) + { + /* Check to see that we have at least the header of the MODE_SENSE response, if not, ignore the data payload. + Some devices do not stall this command but rather return 0 byte length. */ + if(_ux_utility_short_get_big_endian(mode_sense_response + UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_MODE_DATA_LENGTH) >= UX_HOST_CLASS_STORAGE_MODE_SENSE_HEADER_PAGE_LENGTH) + { + + /* The Mode Sense response tells us if the media is Write protected or not. */ + if (*(mode_sense_response + wp_parameter_location) & UX_HOST_CLASS_STORAGE_MODE_SENSE_RESPONSE_ATTRIBUTES_WP) + + /* The Mode Sense response tells us if the media is Write protected or not. */ + storage -> ux_host_class_storage_write_protected_media = UX_TRUE; + } + } + + /* Free the memory resource used for the command response. */ + _ux_utility_memory_free(mode_sense_response); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_read.c b/common/usbx_host_classes/src/ux_host_class_storage_media_read.c new file mode 100644 index 0000000..a96afc5 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_read.c @@ -0,0 +1,155 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_media_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will read one or more logical sector from the media. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* sector_start Starting sector */ +/* sector_count Number of sectors to read */ +/* data_pointer Pointer to data to read */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_cbw_initialize Initialize the CBW */ +/* _ux_host_class_storage_transport Send command */ +/* _ux_utility_long_put_big_endian Put 32-bit word */ +/* _ux_utility_short_put_big_endian Put 16-bit word */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_media_read(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start, + ULONG sector_count, UCHAR *data_pointer) +{ + +UINT status; +UCHAR *cbw; +UINT command_length; +UINT media_retry; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_READ, storage, sector_start, sector_count, data_pointer, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Reset the retry count. */ + media_retry = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY; + + /* We may need several attempts. */ + while (media_retry-- != 0) + { + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Get the Read Command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_READ_COMMAND_LENGTH_SBC; +#endif + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_IN, sector_count * storage -> ux_host_class_storage_sector_size, command_length); + + /* Prepare the MEDIA READ command block. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_READ_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_READ16; + + /* Store the sector start (LBA field). */ + _ux_utility_long_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_READ_LBA, sector_start); + + /* Store the number of sectors to read. */ + _ux_utility_short_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_READ_TRANSFER_LENGTH, (USHORT) sector_count); + + /* Send the command to transport layer. */ + status = _ux_host_class_storage_transport(storage, data_pointer); + if (status != UX_SUCCESS) + return(status); + + /* Did the command succeed? */ + if (storage -> ux_host_class_storage_sense_code == UX_SUCCESS) + { + + /* Check for completeness of sector read. */ + if (storage -> ux_host_class_storage_data_phase_length != sector_count * storage -> ux_host_class_storage_sector_size) + { + + /* This can happen if the device sent less data than the host + requested. This does not fit our definition of success and + retrying shouldn't change the outcome, so we return an error. */ + + /* We got an error during read. Packet not complete. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_DATA_LESS_THAN_EXPECTED); + + /* Return to FileX. */ + return(UX_ERROR); + } + + /* The read succeeded. */ + return(UX_SUCCESS); + } + + /* The command did not succeed. Retry. */ + } + + /* Check if the media in the device has been removed. If so + we have to tell FileX that the media is closed. */ + return(UX_HOST_CLASS_STORAGE_SENSE_ERROR); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_recovery_sense_get.c b/common/usbx_host_classes/src/ux_host_class_storage_media_recovery_sense_get.c new file mode 100644 index 0000000..a865008 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_recovery_sense_get.c @@ -0,0 +1,136 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_media_recovery_sense_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will send a MODE_SENSE command to recover from a read */ +/* and write error. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_cbw_initialize Initialize CBW */ +/* _ux_host_class_storage_transport Send command */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_short_put_big_endian Put short value */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_media_recovery_sense_get(UX_HOST_CLASS_STORAGE *storage) +{ + +UINT status; +UCHAR *cbw; +UCHAR *mode_sense_response; +UINT command_length; + + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Get the Write Command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_MODE_SENSE_COMMAND_LENGTH_SBC; +#endif + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_IN, UX_HOST_CLASS_STORAGE_MODE_SENSE_TP_PAGE, command_length); + + /* Prepare the MODE_SENSE command block. Distinguish between SUBCLASSES. */ + switch (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass) + { + + case UX_HOST_CLASS_STORAGE_SUBCLASS_RBC : +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + case UX_HOST_CLASS_STORAGE_SUBCLASS_UFI : +#endif + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_MODE_SENSE_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_MODE_SENSE; + break; + + default : + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_MODE_SENSE_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_MODE_SENSE_SHORT; + break; + } + + /* We ask for a specific page page but we put the buffer to maximum size. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_MODE_SENSE_PC_PAGE_CODE) = UX_HOST_CLASS_STORAGE_MODE_SENSE_TP_PAGE; + + /* Store the length of the Mode Sense Response. */ + _ux_utility_short_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_MODE_SENSE_PARAMETER_LIST_LENGTH, UX_HOST_CLASS_STORAGE_MODE_SENSE_ALL_PAGE_LENGTH); + + /* Obtain a block of memory for the answer. */ + mode_sense_response = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_MODE_SENSE_ALL_PAGE_LENGTH); + if (mode_sense_response == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Send the command to transport layer. */ + status = _ux_host_class_storage_transport(storage, mode_sense_response); + + /* Free the memory resource used for the command response. */ + _ux_utility_memory_free(mode_sense_response); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_media_write.c b/common/usbx_host_classes/src/ux_host_class_storage_media_write.c new file mode 100644 index 0000000..d67fac9 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_media_write.c @@ -0,0 +1,134 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_media_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will write one or more logical sector to the media. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* sector_start Starting sector */ +/* sector_count Number of sectors to write */ +/* data_pointer Pointer to data to write */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_cbw_initialize Initialize the CBW */ +/* _ux_host_class_storage_transport Send command */ +/* _ux_utility_long_put_big_endian Put 32-bit word */ +/* _ux_utility_short_put_big_endian Put 16-bit word */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_media_write(UX_HOST_CLASS_STORAGE *storage, ULONG sector_start, + ULONG sector_count, UCHAR *data_pointer) +{ + +UINT status; +UCHAR *cbw; +UINT media_retry; +UINT command_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_MEDIA_WRITE, storage, sector_start, sector_count, data_pointer, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Get the Write Command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_WRITE_COMMAND_LENGTH_SBC; +#endif + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_OUT, sector_count * storage -> ux_host_class_storage_sector_size, + command_length); + + /* Prepare the MEDIA WRITE command block. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_WRITE_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_WRITE16; + + /* Store the sector start (LBA field). */ + _ux_utility_long_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_WRITE_LBA, sector_start); + + /* Store the number of sectors to write. */ + _ux_utility_short_put_big_endian(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_WRITE_TRANSFER_LENGTH, (USHORT) sector_count); + + /* Reset the retry count. */ + media_retry = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RETRY; + + /* We may need several attempts. */ + while (media_retry-- != 0) + { + + /* Send the command to transport layer. */ + status = _ux_host_class_storage_transport(storage, data_pointer); + if (status != UX_SUCCESS) + return(status); + + /* Check the sense code */ + if (storage -> ux_host_class_storage_sense_code == UX_SUCCESS) + return(UX_SUCCESS); + } + + /* Return sense error. */ + return(UX_HOST_CLASS_STORAGE_SENSE_ERROR); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_partition_read.c b/common/usbx_host_classes/src/ux_host_class_storage_partition_read.c new file mode 100644 index 0000000..7a79694 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_partition_read.c @@ -0,0 +1,127 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_partition_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will analyze the partition table and parse all the */ +/* partitions. It may happen that a partition entry points to a */ +/* secondary partition table. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* sector_memory Pointer to memory for sector */ +/* sector Sector number */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_media_mount Mount media */ +/* _ux_host_class_storage_media_open Open media */ +/* _ux_utility_long_get Get 32-bit word */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_storage_media_mount Mount media */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_partition_read(UX_HOST_CLASS_STORAGE *storage, UCHAR *sector_memory, ULONG sector) +{ + +UINT status = UX_ERROR; +UINT partition_index; + + + /* Point the sector buffer to the first partition entry. */ + sector_memory += UX_HOST_CLASS_STORAGE_PARTITION_TABLE_START; + + /* There are 4 partitions in a partition table. */ + for (partition_index = 0; partition_index < 4; partition_index++) + { + + /* Check if we recognize this partition entry. */ + switch(*(sector_memory + UX_HOST_CLASS_STORAGE_PARTITION_TYPE)) + { + + case UX_HOST_CLASS_STORAGE_PARTITION_FAT_12: + case UX_HOST_CLASS_STORAGE_PARTITION_FAT_16: + case UX_HOST_CLASS_STORAGE_PARTITION_FAT_16L: + case UX_HOST_CLASS_STORAGE_PARTITION_FAT_16_LBA_MAPPED: + case UX_HOST_CLASS_STORAGE_PARTITION_FAT_32_1: + case UX_HOST_CLASS_STORAGE_PARTITION_FAT_32_2: + + /* We have found a legal partition entry pointing to a potential boot sector. */ + status = _ux_host_class_storage_media_open(storage, sector + _ux_utility_long_get(sector_memory + UX_HOST_CLASS_STORAGE_PARTITION_SECTORS_BEFORE)); + break; + + case UX_HOST_CLASS_STORAGE_PARTITION_EXTENDED: + case UX_HOST_CLASS_STORAGE_PARTITION_EXTENDED_LBA_MAPPED: + + /* We have found an entry to an extended partition. We need to read that partition sector + and recursively mount all partitions found. */ + status = _ux_host_class_storage_media_mount(storage, sector + _ux_utility_long_get(sector_memory + UX_HOST_CLASS_STORAGE_PARTITION_SECTORS_BEFORE)); + break; + + default: + + /* We have found something which is not a DOS recognized partition, or an empty entry. + Ignore it and proceed with the rest. */ + break; + } + + /* Move to the next partition entry. */ + sector_memory += UX_HOST_CLASS_STORAGE_PARTITION_TABLE_SIZE; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_request_sense.c b/common/usbx_host_classes/src/ux_host_class_storage_request_sense.c new file mode 100644 index 0000000..bf0701c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_request_sense.c @@ -0,0 +1,152 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_request_sense PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will send a request sense to the device to see what */ +/* error happened during the last command. Request sense commands */ +/* cannot be nested. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_cbw_initialize Initialize CBW */ +/* _ux_host_class_storage_transport Send command */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_copy Copy memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_request_sense(UX_HOST_CLASS_STORAGE *storage) +{ + +UINT status; +UCHAR *cbw; +UCHAR *request_sense_response; +ULONG sense_code; +UINT command_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_REQUEST_SENSE, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Clear the former sense code value. */ + storage -> ux_host_class_storage_sense_code = 0; + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Get the Request Sense Command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_COMMAND_LENGTH_SBC; +#endif + + /* Check of we are reentering a REQUEST SENSE command which is illegal. */ + if (*(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_OPERATION) == UX_HOST_CLASS_STORAGE_SCSI_REQUEST_SENSE) + return(UX_ERROR); + + /* Save the current command so that we can re-initiate it after the + REQUEST_SENSE command. */ + _ux_utility_memory_copy(storage -> ux_host_class_storage_saved_cbw, storage -> ux_host_class_storage_cbw, UX_HOST_CLASS_STORAGE_CBW_LENGTH); + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, UX_HOST_CLASS_STORAGE_DATA_IN, UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH, command_length); + + /* Prepare the REQUEST SENSE command block. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_REQUEST_SENSE; + + /* Store the length of the Request Sense Response. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_ALLOCATION_LENGTH) = UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH; + + /* Obtain a block of memory for the answer. */ + request_sense_response = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_LENGTH); + if (request_sense_response == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Send the command to transport layer. */ + status = _ux_host_class_storage_transport(storage, request_sense_response); + + /* If we have a transport error, there is not much we can do, simply return the error. */ + if (status == UX_SUCCESS) + { + + /* We have a successful transaction, even though the sense code could reflect an error. The sense code + will be assembled and store in the device instance. */ + sense_code = (((ULONG) *(request_sense_response + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_SENSE_KEY)) & 0x0f) << 16; + sense_code |= ((ULONG) *(request_sense_response + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE)) << 8; + sense_code |= (ULONG) *(request_sense_response + UX_HOST_CLASS_STORAGE_REQUEST_SENSE_RESPONSE_CODE_QUALIFIER); + + /* Store the sense code in the storage instance. */ + storage -> ux_host_class_storage_sense_code = sense_code; + } + + /* Free the memory resource used for the command response. */ + _ux_utility_memory_free(request_sense_response); + + /* Restore the current CBW command. */ + _ux_utility_memory_copy(storage -> ux_host_class_storage_cbw, storage -> ux_host_class_storage_saved_cbw, UX_HOST_CLASS_STORAGE_CBW_LENGTH); + + /* Return completion code. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_sense_code_translate.c b/common/usbx_host_classes/src/ux_host_class_storage_sense_code_translate.c new file mode 100644 index 0000000..9d630ce --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_sense_code_translate.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_sense_code_translate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will perform a conversion between the SCSI error */ +/* codes and error codes expected by FileX. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* status Status to convert */ +/* */ +/* OUTPUT */ +/* */ +/* Converted Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_sense_code_translate(UX_HOST_CLASS_STORAGE *storage, UINT status) +{ + + UX_PARAMETER_NOT_USED(storage); + + /* Return status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_start_stop.c b/common/usbx_host_classes/src/ux_host_class_storage_start_stop.c new file mode 100644 index 0000000..53bf7e9 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_start_stop.c @@ -0,0 +1,127 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_start_stop.c PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts or stops the UFI device. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* start_stop_flag 1 or 0 if start/stop */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_cbw_initialize Initialize the CBW */ +/* _ux_host_class_storage_transport Send transport layer command */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_start_stop(UX_HOST_CLASS_STORAGE *storage, + ULONG start_stop_signal) +{ + +UINT status; +UCHAR *cbw; +UINT command_length; +ULONG command_retry; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_START_STOP, storage, start_stop_signal, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Use a pointer for the CBW, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Get the START_STOP Command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_START_STOP_COMMAND_LENGTH_SBC; +#endif + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, 0, 0, command_length); + + /* Prepare the START STOP command block. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_START_STOP_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_START_STOP; + + /* Set the required signal. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_START_STOP_START_BIT) = (UCHAR) start_stop_signal; + + /* On floppies, this operation tends to fail a few times. So we try harder. */ + for (command_retry = 0; command_retry < 50; command_retry++) + { + + /* Send the command to transport layer. */ + status = _ux_host_class_storage_transport(storage, UX_NULL); + + /* If we have a transport error give up. */ + if(status != UX_SUCCESS) + + /* Return completion status. */ + return(status); + + /* Check the CSW. We may learn something there about the state of the device. */ + if (storage -> ux_host_class_storage_sense_code == 0) + return(UX_SUCCESS); + } + + /* The start/Stop did not work. */ + return(UX_ERROR); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_thread_entry.c b/common/usbx_host_classes/src/ux_host_class_storage_thread_entry.c new file mode 100644 index 0000000..8d6b056 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_thread_entry.c @@ -0,0 +1,306 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_thread_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is awaken every 2 seconds to check if there was a */ +/* device insertion on a specific media. This is the only way we can */ +/* remount a media after the storage instance has opened the media to */ +/* FileX and the media is either not present or was removed and is */ +/* being re-)inserted. */ +/* */ +/* INPUT */ +/* */ +/* class_address Class address */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* fx_media_close Close FileX media */ +/* _ux_host_class_storage_device_reset Reset device */ +/* _ux_host_class_storage_media_mount Mount the media */ +/* _ux_host_class_storage_unit_ready_test */ +/* Test for unit ready */ +/* _ux_host_class_storage_media_characteristics_get */ +/* Get media characteristics */ +/* _ux_host_class_storage_media_format_capacity_get */ +/* Get media format capacity */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_get Get a semaphore */ +/* _ux_utility_semaphore_put Put a semaphore */ +/* _ux_utility_delay_ms Thread sleep */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_storage_thread_entry(ULONG class_address) +{ + +UX_HOST_CLASS *class; +UX_HOST_CLASS_STORAGE *storage; +UINT status; +ULONG lun_index; +UX_HOST_CLASS_STORAGE_MEDIA *storage_media; +FX_MEDIA *media; +UCHAR *memory; +UINT media_index; + + + /* Setup pointer to class. */ + UX_THREAD_EXTENSION_PTR_GET(class, UX_HOST_CLASS, class_address) + + /* This thread goes on forever once started. */ + while(1) + { + + /* We need to wake every 2 seconds or so. */ + _ux_utility_delay_ms(UX_HOST_CLASS_STORAGE_THREAD_SLEEP_TIME); + + /* We need to parse all the storage instances and check for a removable + media flag. */ + storage = (UX_HOST_CLASS_STORAGE *) class -> ux_host_class_first_instance; + + while (storage != UX_NULL) + { + + /* Check if the instance is live and the device is removable. */ + if ((storage -> ux_host_class_storage_state == UX_HOST_CLASS_INSTANCE_LIVE)) + { + + /* We need to ensure nobody is accessing this storage instance. We use + the storage class instance semaphore to protect. */ + status = _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + break; + + /* Each LUN must be parsed and mounted. */ + for (lun_index = 0; lun_index <= storage -> ux_host_class_storage_max_lun; lun_index++) + { + + if (storage -> ux_host_class_storage_lun_removable_media_flags[lun_index] != UX_HOST_CLASS_STORAGE_MEDIA_REMOVABLE) + continue; + + /* Check the type of LUN, we only deal with the ones we know how to mount. */ + if ((storage -> ux_host_class_storage_lun_types[lun_index] == UX_HOST_CLASS_STORAGE_MEDIA_FAT_DISK) || + (storage -> ux_host_class_storage_lun_types[lun_index] == UX_HOST_CLASS_STORAGE_MEDIA_OPTICAL_DISK) || + (storage -> ux_host_class_storage_lun_types[lun_index] == UX_HOST_CLASS_STORAGE_MEDIA_IOMEGA_CLICK)) + { + + /* Set the LUN into the storage instance. */ + storage -> ux_host_class_storage_lun = lun_index; + + /* Check if the device is now ready. */ + status = _ux_host_class_storage_unit_ready_test(storage); + + /* If we have an transport failure here, we are in trouble! The storage device + is in an unstable state and should be reset completely. */ + if (status != UX_SUCCESS) + { + + /* Reset device. */ + _ux_host_class_storage_device_reset(storage); + break; + } + + /* Process relative to device status. */ + switch(storage -> ux_host_class_storage_sense_code >> 16) + { + + case UX_HOST_CLASS_STORAGE_SENSE_KEY_NOT_READY: + + /* We may need to unmount this partition if it was mounted before. + To do so, we need to parse the existing media instance and find out + if this partition was already mounted. */ + + storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) class -> ux_host_class_media; + + /* Scan all instances of media. */ + for (media_index = 0; media_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA; media_index++) + { + + /* Get the FileX Media attached to this media. */ + media = &storage_media -> ux_host_class_storage_media; + + /* Check for the storage instance and lun number. */ + if ((media -> fx_media_id != 0) && (media -> fx_media_driver_info == (VOID *) storage) && + (storage_media -> ux_host_class_storage_media_lun == storage -> ux_host_class_storage_lun)) + { + + /* We preserve the memory used by this media. */ + memory = storage_media -> ux_host_class_storage_media_memory; + + /* Let FileX use this instance. */ + status = _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); + + /* Ask FileX to unmount the partition. */ + fx_media_close(media); + + /* This device is now unmounted. */ + storage_media -> ux_host_class_storage_media_status = UX_HOST_CLASS_STORAGE_MEDIA_UNMOUNTED; + + /* Reset the media ID. */ + media -> fx_media_id = 0; + + /* Now, we protect the storage instance. */ + status = _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + break; + + /* Free the memory block used for data transfer on behalf of FileX. */ + _ux_utility_memory_free(memory); + } + + /* Next entry in the media array. */ + storage_media++; + } + break; + + case UX_HOST_CLASS_STORAGE_SENSE_KEY_UNIT_ATTENTION: + + /* We may need to unmount this partition if it was mounted before. + To do so, we need to parse the existing media instance and find out + if this partition was already mounted. */ + storage_media = (UX_HOST_CLASS_STORAGE_MEDIA *) class -> ux_host_class_media; + + /* Scan all instances of media. */ + for (media_index = 0; media_index < UX_HOST_CLASS_STORAGE_MAX_MEDIA; media_index++) + { + + /* Get the FileX Media attached to this media. */ + media = &storage_media -> ux_host_class_storage_media; + + /* Check for the storage instance and lun number. */ + if ((media -> fx_media_id != 0) && (media -> fx_media_driver_info == (VOID *) storage) && + (storage_media -> ux_host_class_storage_media_lun == storage -> ux_host_class_storage_lun)) + { + + /* We preserve the memory used by this media. */ + memory = storage_media -> ux_host_class_storage_media_memory; + + /* Let FileX use this instance. */ + status = _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); + + /* Ask FileX to unmount the partition. */ + fx_media_close(media); + + /* This device is now unmounted. */ + storage_media -> ux_host_class_storage_media_status = UX_HOST_CLASS_STORAGE_MEDIA_UNMOUNTED; + + /* Reset the media ID. */ + media -> fx_media_id = 0; + + /* Now, we protect the storage instance. */ + status = _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + break; + + /* Free the memory block used for data transfer on behalf of FileX. */ + _ux_utility_memory_free(memory); + } + + /* Next entry in the media array. */ + storage_media++; + } + + /* Now, we need to retest the media to see if it is there. */ + status = _ux_host_class_storage_unit_ready_test(storage); + + /* If we have an transport failure here, we are in trouble! The storage device + is in an unstable state and should be reset completely. */ + if (status != UX_SUCCESS) + { + + /* Reset device. */ + _ux_host_class_storage_device_reset(storage); + break; + } + + if (storage -> ux_host_class_storage_sense_code == 0) + { + + /* Get the media type supported by this storage device. */ + status = _ux_host_class_storage_media_characteristics_get(storage); + if (status != UX_SUCCESS) + break; + + /* Get the format capacity of this storage device. */ + status = _ux_host_class_storage_media_format_capacity_get(storage); + if (status != UX_SUCCESS) + break; + + /* Let FileX use this instance. */ + _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); + + /* The device seems to have been inserted, try to mount it. */ + _ux_host_class_storage_media_mount(storage, 0); + + /* Now, we protect the storage instance. */ + _ux_utility_semaphore_get(&storage -> ux_host_class_storage_semaphore, UX_WAIT_FOREVER); + } + break; + + default: + break; + } + } + } + + /* Other threads are now allowed to access this storage instance. */ + status = _ux_utility_semaphore_put(&storage -> ux_host_class_storage_semaphore); + } + + /* Move to the next entry in the storage instances link. */ + storage = storage -> ux_host_class_storage_next_instance; + } + } +} diff --git a/common/usbx_host_classes/src/ux_host_class_storage_transport.c b/common/usbx_host_classes/src/ux_host_class_storage_transport.c new file mode 100644 index 0000000..27f9d62 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_transport.c @@ -0,0 +1,154 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_transport PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the transport layer for all protocols. It perform */ +/* the error recovery and retries if needed. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* data_pointer Pointer to data */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_storage_transport) Class storage transport */ +/* _ux_host_class_storage_device_reset Reset device */ +/* _ux_host_class_storage_request_sense Class request sense */ +/* _ux_host_stack_endpoint_reset Reset endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_transport(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer) +{ + +UINT status; +UINT csw_status; + + + /* Reset the sense code. */ + storage -> ux_host_class_storage_sense_code = UX_SUCCESS; + + /* Send the command to the appropriate transport. */ + status = storage -> ux_host_class_storage_transport(storage, data_pointer); + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + /* The treatment of errors is different according to the protocol used. BO and CB belong + to the CSW group. CBI is separate. */ + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceProtocol != UX_HOST_CLASS_STORAGE_PROTOCOL_CBI) + { +#endif + + /* Check the status. */ + if (status != UX_SUCCESS) + + /* There was a more serious error. Just give up! */ + return(status); + + /* The command transfer was OK but maybe we have a CSW error. */ + csw_status = storage -> ux_host_class_storage_csw[UX_HOST_CLASS_STORAGE_CSW_STATUS]; + if (csw_status == 0) + return(UX_SUCCESS); + + /* Check for a command failure. If so, we need to sense the error with + a REQUEST SENSE command. */ + status = _ux_host_class_storage_request_sense(storage); + + /* If we have an transport failure here, we are in trouble! The storage device is in + an unstable state and should be reset completely. */ + if (status != UX_SUCCESS) + { + + /* Reset device. */ + _ux_host_class_storage_device_reset(storage); + return(status); + } + + /* The sense code is saved in the device instance. We can return safely. */ + return(UX_SUCCESS); + +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + } + else + { + + switch (status) + { + + case UX_SUCCESS: + return(UX_SUCCESS); + + case UX_TRANSFER_STALLED: + + /* The endpoint was halted by a stall condition and needs to be reset. */ + _ux_host_stack_endpoint_reset(storage -> ux_host_class_storage_bulk_in_endpoint); + + /* The endpoint was halted by a stall condition and needs to be reset. */ + _ux_host_stack_endpoint_reset(storage -> ux_host_class_storage_bulk_out_endpoint); + + /* Check for a command failure. If so, we need to sense the error with + a REQUEST SENSE command. */ + status = _ux_host_class_storage_request_sense(storage); + return(status); + + default: + + /* There was a more serious error. Just give up! */ + return(status); + } + } +#endif +} diff --git a/common/usbx_host_classes/src/ux_host_class_storage_transport_bo.c b/common/usbx_host_classes/src/ux_host_class_storage_transport_bo.c new file mode 100644 index 0000000..26a6645 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_transport_bo.c @@ -0,0 +1,387 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_transport_bo PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the transport layer for the Bulk Only protocol. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* data_pointer Pointer to data */ +/* */ +/* OUTPUT */ +/* */ +/* The transfer completion status. It's possible for the transfer to */ +/* succeed but for the command to fail. The CSW must be checked to */ +/* determine command status. */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_device_reset Reset mass storage */ +/* _ux_host_stack_endpoint_reset Reset endpoint */ +/* _ux_host_stack_transfer_request Process host stack transfer */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_utility_long_get Get 32-bit word */ +/* _ux_utility_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_transport_bo(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer) +{ + +UX_TRANSFER *transfer_request; +UINT status; +UCHAR *cbw; +UINT retry; +ULONG data_phase_requested_length; +ULONG data_phase_transfer_size; +UCHAR *get_status_response; + + + /* Get the pointer to the transfer request. */ + transfer_request = &storage -> ux_host_class_storage_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Use a pointer for the cbw, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Fill in the transfer request parameters. */ + transfer_request -> ux_transfer_request_data_pointer = cbw; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_STORAGE_CBW_LENGTH; + + /* It's possible for the bulk out endpoint to stall; in that case, we clear + it and try again. */ + for (retry = 0; ; retry++) + { + + /* Send the CBW on the bulk out endpoint. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check the status of the command (NB, the command is not sent yet since + the bulk transport is non blocking). */ + if (status != UX_SUCCESS) + return(status); + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + + /* Did we successfully send the CBW? */ + if (transfer_request -> ux_transfer_request_completion_code == UX_SUCCESS) + + /* Jump to the data stage. */ + break; + + /* The transfer stalled. Is this the first time? */ + if (retry == 0) + { + + /* We must do a reset recovery. */ + _ux_host_class_storage_device_reset(storage); + + /* In virtually all cases, the reset should've fixed it, so just + resend the command. */ + } + else + { + + /* Well, we tried! */ + return(transfer_request -> ux_transfer_request_completion_code); + } + } + + /* Get the length of the data payload. */ + data_phase_requested_length = _ux_utility_long_get(cbw + UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH); + + /* Reset the data phase memory size. */ + storage -> ux_host_class_storage_data_phase_length = 0; + + /* Perform the data stage - if there is any. */ + while (data_phase_requested_length != 0) + { + + /* Check if we can finish the transaction with one data phase. */ + if (data_phase_requested_length > UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE) + + /* We have too much data to send in one phase. Split into smaller chunks. */ + data_phase_transfer_size = UX_HOST_CLASS_STORAGE_MAX_TRANSFER_SIZE; + + else + + /* The transfer size can be the requested length. */ + data_phase_transfer_size = data_phase_requested_length; + + /* Check the direction and determine which endpoint to use. */ + if (*(cbw + UX_HOST_CLASS_STORAGE_CBW_FLAGS) == UX_HOST_CLASS_STORAGE_DATA_IN) + transfer_request = &storage -> ux_host_class_storage_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Fill in the transfer request data payload buffer. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + + /* Store the requested length in the transfer request. */ + transfer_request -> ux_transfer_request_requested_length = data_phase_transfer_size; + + /* Perform data payload transfer (in or out). */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check the status of the data payload. */ + if (status == UX_SUCCESS) + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we may have a time out or if we had a problem during the preparation of the transaction + we should abort the SCSI transaction. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error that cannot be recovered, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + + /* Check the transfer status. If there is a transport error, we still need to read the CSW + and let the upper layer retry. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* This is most likely a STALL. We must clear it and go straight + to reading the CSW. Note this doesn't necessarily mean the transfer + failed completely failed. For example, if this was a read, it + could mean the device had less data to send than we requested, + but we still received data. */ + + /* Check the direction and determine which endpoint to reset. */ + if (*(cbw + UX_HOST_CLASS_STORAGE_CBW_FLAGS) == UX_HOST_CLASS_STORAGE_DATA_IN) + _ux_host_stack_endpoint_reset(storage -> ux_host_class_storage_bulk_in_endpoint); + else + _ux_host_stack_endpoint_reset(storage -> ux_host_class_storage_bulk_out_endpoint); + + /* We need to read the CSW now. */ + break; + } + + /* Adjust the total size that was requested. */ + data_phase_requested_length -= data_phase_transfer_size; + + /* And the data pointer. */ + data_pointer += data_phase_transfer_size; + } + + /* Now perform the status phase, i.e. try to get the CSW from the device. + According to the spec, if there is a failure the first time, we need to retry once + before reporting an error. */ + + /* Get the pointer to the transfer request, on the bulk in endpoint. */ + transfer_request = &storage -> ux_host_class_storage_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Fill in the transfer_request parameters. */ + transfer_request -> ux_transfer_request_data_pointer = (UCHAR *) &storage -> ux_host_class_storage_csw; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_STORAGE_CSW_LENGTH; + + /* Retry loop, we have 2 tries here. */ + for (retry = 0; retry < 2; retry++) + { + + /* Get the CSW on the bulk in endpoint. */ + status = _ux_host_stack_transfer_request(transfer_request); + if (status != UX_SUCCESS) + return(status); + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); + + /* Check semaphore status. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + + /* Did the transfer succeed? */ + if (transfer_request -> ux_transfer_request_completion_code == UX_SUCCESS) + { + + /* The PASSED and COMMAND_FAILED error codes are nearly interchangeable + according to the spec, so we treat them similarly. */ + if (storage -> ux_host_class_storage_csw[UX_HOST_CLASS_STORAGE_CSW_STATUS] == UX_HOST_CLASS_STORAGE_CSW_PASSED || + storage -> ux_host_class_storage_csw[UX_HOST_CLASS_STORAGE_CSW_STATUS] == UX_HOST_CLASS_STORAGE_CSW_FAILED) + { + + /* Was this an OUT transport? */ + if (*(cbw + UX_HOST_CLASS_STORAGE_CBW_FLAGS) == UX_HOST_CLASS_STORAGE_DATA_OUT) + { + + /* Did the command fail, or succeed with non-zero data residue? */ + if (storage -> ux_host_class_storage_csw[UX_HOST_CLASS_STORAGE_CSW_STATUS] == UX_HOST_CLASS_STORAGE_CSW_FAILED || + _ux_utility_long_get(storage -> ux_host_class_storage_csw + UX_HOST_CLASS_STORAGE_CSW_DATA_RESIDUE) != 0) + { + + /* It's possible the bulk out endpoint is stalled. + This happens when 1) the device expects less data + than the host wants to send and 2) the endpoint + stalls after the last packet was sent (otherwise, + we'd have seen the stall during the data stage). + Query its status before clearing the stall. */ + + /* Allocate memory for Get Status response. */ + get_status_response = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 2); + if (get_status_response == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Get the control endpoint's transfer request. */ + transfer_request = &storage -> ux_host_class_storage_device -> ux_device_control_endpoint.ux_endpoint_transfer_request; + + /* Setup transfer request for Get Status command. */ + transfer_request -> ux_transfer_request_data_pointer = get_status_response; + transfer_request -> ux_transfer_request_requested_length = 0x02; + transfer_request -> ux_transfer_request_function = UX_GET_STATUS; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_ENDPOINT; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = storage -> ux_host_class_storage_bulk_out_endpoint-> ux_endpoint_descriptor.bEndpointAddress; + + /* Send transfer request. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check status of transfer. */ + if (status == UX_SUCCESS) + { + + /* Check the Halt bit. */ + if (get_status_response[0] & 0x01) + { + + /* Clear the halt. */ + status = _ux_host_stack_endpoint_reset(storage -> ux_host_class_storage_bulk_out_endpoint); + } + } + + /* Free the get status memory. */ + _ux_utility_memory_free(get_status_response); + + /* Check result of Get Status and Clear Feature commands. */ + if (status != UX_SUCCESS) + return(status); + } + } + + /* Save the amount of relevant data. */ + storage -> ux_host_class_storage_data_phase_length = _ux_utility_long_get(cbw + UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH) - + _ux_utility_long_get(storage -> ux_host_class_storage_csw + UX_HOST_CLASS_STORAGE_CSW_DATA_RESIDUE); + } + else + { + + /* Must be phase error. Need to reset the device. */ + _ux_host_class_storage_device_reset(storage); + } + + /* Return success since the transfer succeeded. The caller should + look at the CSW to determine if the command's status. */ + return(UX_SUCCESS); + } + + /* The transfer stalled. We must clear the stall and attempt to read + the CSW again. */ + _ux_host_stack_endpoint_reset(storage -> ux_host_class_storage_bulk_in_endpoint); + } + + /* If we get here, the CSW transfer stalled twice. We must reset the device. */ + _ux_host_class_storage_device_reset(storage); + + /* Return the error. */ + return(transfer_request -> ux_transfer_request_completion_code); +} diff --git a/common/usbx_host_classes/src/ux_host_class_storage_transport_cb.c b/common/usbx_host_classes/src/ux_host_class_storage_transport_cb.c new file mode 100644 index 0000000..ab9af48 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_transport_cb.c @@ -0,0 +1,176 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_transport_cb PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the transport layer for the Control/Bulk */ +/* transport. The command is sent on the control endpoint and the */ +/* data payload on the bulk endpoint. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* data_pointer Pointer to data */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process host stack transfer */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_long_get Get 32-bit word */ +/* _ux_utility_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_transport_cb(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer) +{ + +UX_TRANSFER *transfer_request; +UINT status; +UCHAR *ufi; +UCHAR *cbw; +ULONG data_phase_requested_length; +UX_ENDPOINT *control_endpoint; + + + /* Reset the data phase memory size. */ + storage -> ux_host_class_storage_data_phase_length = 0; + + /* We need to get the default control endpoint transfer request pointer */ + control_endpoint = &storage -> ux_host_class_storage_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Initialize the transfer request with the control SETUP values. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = 0; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Use a pointer for the ufi portion of the command. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + ufi = cbw + UX_HOST_CLASS_STORAGE_CBW_CB; + + /* Fill in the transfer request parameters. */ + transfer_request -> ux_transfer_request_data_pointer = ufi; + transfer_request -> ux_transfer_request_requested_length = (ULONG) * (cbw + UX_HOST_CLASS_STORAGE_CBW_CB_LENGTH); + + /* Send the ufi block on the control endpoint. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check the transfer status. If there is a transport error, the host must perform + a reset recovery. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + return(transfer_request -> ux_transfer_request_completion_code); + + /* Get the length of the data payload. */ + data_phase_requested_length = _ux_utility_long_get(cbw + UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH); + + /* Perform the data stage - if there is any. */ + if (data_phase_requested_length != 0) + { + + /* Check the direction and determine which endpoint to use. */ + if (*(cbw + UX_HOST_CLASS_STORAGE_CBW_FLAGS) == UX_HOST_CLASS_STORAGE_DATA_IN) + transfer_request = &storage -> ux_host_class_storage_bulk_in_endpoint -> ux_endpoint_transfer_request; + else + transfer_request = &storage -> ux_host_class_storage_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Fill in the transfer request data payload buffer. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + + /* Store the requested length in the transfer request. */ + transfer_request -> ux_transfer_request_requested_length = data_phase_requested_length; + + /* Perform data payload transfer (in or out). */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check the status of the data payload. */ + if (status != UX_SUCCESS) + return(status); + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); + + /* Get the actual transfer length and update the cumulated stored value for upper layers. + This could be a non complete packet. But we don't test here because it only matters for + sector read. */ + storage -> ux_host_class_storage_data_phase_length += transfer_request -> ux_transfer_request_actual_length; + + /* If the semaphore did not succeed we probably have a timeout. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + } + + /* Return the status code. */ + return(transfer_request -> ux_transfer_request_completion_code); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_transport_cbi.c b/common/usbx_host_classes/src/ux_host_class_storage_transport_cbi.c new file mode 100644 index 0000000..5fba387 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_transport_cbi.c @@ -0,0 +1,199 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_transport_cbi PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the transport layer for the Control/Bulk/Interrupt */ +/* transport. The command is sent on the control endpoint, the data */ +/* payload on the bulk endpoint. The status from the command is */ +/* returned by the interrupt endpoint. This transport is mainly used */ +/* by storage devices that have very slow read/write commands. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* data_pointer Pointer to data */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process host stack transfer */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_long_get Get 32-bit word */ +/* _ux_utility_semaphore_get Get semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_transport_cbi(UX_HOST_CLASS_STORAGE *storage, UCHAR *data_pointer) +{ + +UX_TRANSFER *transfer_request; +UINT status; +UCHAR *ufi; +UCHAR *cbw; +ULONG data_phase_requested_length; +UX_ENDPOINT *control_endpoint; + + + /* Reset the data phase memory size. */ + storage -> ux_host_class_storage_data_phase_length = 0; + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &storage -> ux_host_class_storage_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Initialize the transfer request with the control SETUP values. */ + transfer_request -> ux_transfer_request_data_pointer = UX_NULL; + transfer_request -> ux_transfer_request_requested_length = 0; + transfer_request -> ux_transfer_request_function = 0; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = 0; + transfer_request -> ux_transfer_request_index = 0; + + /* Use a pointer for the ufi portion of the command. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + ufi = cbw + UX_HOST_CLASS_STORAGE_CBW_CB; + + /* Fill in the transfer_request parameters. */ + transfer_request -> ux_transfer_request_data_pointer = ufi; + transfer_request -> ux_transfer_request_requested_length = (ULONG)*(cbw+UX_HOST_CLASS_STORAGE_CBW_CB_LENGTH); + + /* Send the ufi block on the control endpoint. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check the transfer status. If there is a transport error, the host must perform + a reset recovery. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + return(transfer_request -> ux_transfer_request_completion_code); + + /* Get the length of the data payload. */ + data_phase_requested_length = _ux_utility_long_get(cbw+UX_HOST_CLASS_STORAGE_CBW_DATA_LENGTH); + + /* Perform the data stage - if there is any. */ + if (data_phase_requested_length != 0) + { + + /* Check the direction and determine which endpoint to use. */ + if (*(cbw+UX_HOST_CLASS_STORAGE_CBW_FLAGS) == UX_HOST_CLASS_STORAGE_DATA_IN) + transfer_request = &storage -> ux_host_class_storage_bulk_in_endpoint -> ux_endpoint_transfer_request; + else + transfer_request = &storage -> ux_host_class_storage_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Fill in the transfer_request data payload buffer. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + + /* Store the requested length in the transfer request. */ + transfer_request -> ux_transfer_request_requested_length = data_phase_requested_length; + + /* Perform data payload transfer (in or out). */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check the status of the data payload. */ + if (status != UX_SUCCESS) + return(status); + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_STORAGE_TRANSFER_TIMEOUT)); + + /* Get the actual transfer length and update the cumulated stored value for upper layers. + This could be a non complete packet. But we don't test here because it only matters for + sector read. */ + storage -> ux_host_class_storage_data_phase_length += transfer_request -> ux_transfer_request_actual_length; + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + + /* We need to check the completion code as well. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + return(transfer_request -> ux_transfer_request_completion_code); + + } + + /* Arm the interrupt endpoint with a transfer request. */ + transfer_request = &storage -> ux_host_class_storage_interrupt_endpoint -> ux_endpoint_transfer_request; + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check the status of the data payload. */ + if (status != UX_SUCCESS) + return(status); + + /* We must wait for the interrupt endpoint to return the status stage now. This can + take a fairly long time. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_STORAGE_CBI_STATUS_TIMEOUT)); + + /* If the status is not successful, we may have a timeout error. */ + if (status != UX_SUCCESS) + return(status); + + /* Return the status code. */ + return(transfer_request -> ux_transfer_request_completion_code); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_storage_unit_ready_test.c b/common/usbx_host_classes/src/ux_host_class_storage_unit_ready_test.c new file mode 100644 index 0000000..ef97201 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_storage_unit_ready_test.c @@ -0,0 +1,108 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Storage Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_storage.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_storage_unit_ready_test PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will verify that a SCSI unit is ready for data */ +/* transfer. This command is used when the device does not mount */ +/* when power is supplied. */ +/* */ +/* INPUT */ +/* */ +/* storage Pointer to storage class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_storage_cbw_initialize Initialize the CBW */ +/* _ux_host_class_storage_transport Send transport layer command */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_storage_unit_ready_test(UX_HOST_CLASS_STORAGE *storage) +{ + +UINT status; +UCHAR *cbw; +UINT command_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_STORAGE_UNIT_READY_TEST, storage, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Use a pointer for the CBW, easier to manipulate. */ + cbw = (UCHAR *) storage -> ux_host_class_storage_cbw; + + /* Get the Unit Ready Test Command Length. */ +#ifdef UX_HOST_CLASS_STORAGE_INCLUDE_LEGACY_PROTOCOL_SUPPORT + if (storage -> ux_host_class_storage_interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_STORAGE_SUBCLASS_UFI) + command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_UFI; + else + command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC; +#else + command_length = UX_HOST_CLASS_STORAGE_TEST_READY_COMMAND_LENGTH_SBC; +#endif + + /* Initialize the CBW for this command. */ + _ux_host_class_storage_cbw_initialize(storage, 0, 0, command_length); + + /* Prepare the TEST UNIT READY command block. */ + *(cbw + UX_HOST_CLASS_STORAGE_CBW_CB + UX_HOST_CLASS_STORAGE_TEST_READY_OPERATION) = UX_HOST_CLASS_STORAGE_SCSI_TEST_READY; + + /* Send the command to transport layer. */ + status = _ux_host_class_storage_transport(storage, UX_NULL); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_swar_activate.c b/common/usbx_host_classes/src/ux_host_class_swar_activate.c new file mode 100644 index 0000000..c59f509 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_swar_activate.c @@ -0,0 +1,155 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_swar.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_swar_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to activate the class. */ +/* */ +/* INPUT */ +/* */ +/* command Dpump class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_swar_configure Configure swar class */ +/* _ux_host_class_swar_endpoints_get Get endpoints of swar */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_create Create swar semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_swar_entry Entry of swar class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_swar_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_DEVICE *device; +UX_HOST_CLASS_SWAR *swar; +UINT status; + + + /* The Sierra Wireless class is always activated by the device descriptor. */ + device = (UX_DEVICE *) command -> ux_host_class_command_container; + + /* Obtain memory for this class instance. */ + swar = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS_SWAR)); + if (swar == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance. */ + swar -> ux_host_class_swar_class = command -> ux_host_class_command_class_ptr; + + /* Store the device container into the swar class instance. */ + swar -> ux_host_class_swar_device = device; + + /* Store the instance in the device container, this is for the USBX stack + when it needs to invoke the class for deactivation. */ + device -> ux_device_class_instance = (VOID *) swar; + + /* Create this class instance. */ + _ux_host_stack_class_instance_create(swar -> ux_host_class_swar_class, (VOID *) swar); + + /* Configure the swar. */ + status = _ux_host_class_swar_configure(swar); + + /* Get the swar endpoint(s). We will need to search for Bulk Out and Bulk In endpoints on interface . */ + if (status == UX_SUCCESS) + status = _ux_host_class_swar_endpoints_get(swar); + + /* Create the semaphore to protect 2 threads from accessing the same swar instance. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&swar -> ux_host_class_swar_semaphore, "ux_host_class_swar_semaphore", 1); + if (status != UX_SUCCESS) + status = UX_SEMAPHORE_ERROR; + } + + /* Success things. */ + if (status == UX_SUCCESS) + { + + /* Mark the swar as live now. */ + swar -> ux_host_class_swar_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, swar -> ux_host_class_swar_class, (VOID *) swar); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_SWAR_ACTIVATE, swar, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, swar, 0, 0, 0) + + /* Return success. */ + return(UX_SUCCESS); + } + + /* There was a problem during the configuration, so free the resources. */ + /* The last resource, semaphore is not created or created error, no need to free. */ + _ux_host_stack_class_instance_destroy(swar -> ux_host_class_swar_class, (VOID *) swar); + device -> ux_device_class_instance = UX_NULL; + _ux_utility_memory_free(swar); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_swar_configure.c b/common/usbx_host_classes/src/ux_host_class_swar_configure.c new file mode 100644 index 0000000..bc118b0 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_swar_configure.c @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_swar.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_swar_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to the */ +/* swar. Once the swar is configured, its interface will be */ +/* activated. The bulk endpoints enumerated(1 IN, 1 OUT ). */ +/* */ +/* INPUT */ +/* */ +/* swar Pointer to swar class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get Get interface */ +/* _ux_host_stack_device_configuration_get Get configuration */ +/* _ux_host_stack_device_configuration_select Select configuration */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_swar_activate swar class activate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_swar_configure(UX_HOST_CLASS_SWAR *swar) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_DEVICE *parent_device; + + + /* If the device has been configured already, we don't need to do it + again. */ + if (swar -> ux_host_class_swar_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* A swar normally has one configuration. So retrieve the 1st configuration + only. */ + status = _ux_host_stack_device_configuration_get(swar -> ux_host_class_swar_device, 0, &configuration); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, swar -> ux_host_class_swar_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + } + + /* Check the swar power source and check the parent power source for + incompatible connections. */ + if (swar -> ux_host_class_swar_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* Get parent device pointer. */ + parent_device = swar -> ux_host_class_swar_device -> ux_device_parent; + + /* If the device is NULL, the parent is the root swar and we don't have to worry + if the parent is not the root swar, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, swar, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration. */ + status = _ux_host_stack_device_configuration_select(configuration); + if (status != UX_SUCCESS) + return(status); + + /* If the operation went well, the swar default alternate setting for the swar interface is + active. We have to memorize the data interface since the bulk in/out endpoints are hooked to it. */ + status = _ux_host_stack_configuration_interface_get(configuration, UX_HOST_CLASS_SWAR_DATA_INTERFACE, 0, &swar -> ux_host_class_swar_interface); + if (status == UX_SUCCESS) + { + + /* Store the instance in the interface container, this is for the USB stack + when it needs to invoke the class. */ + swar -> ux_host_class_swar_interface -> ux_interface_class_instance = (VOID *) swar; + + /* Store the class container in the interface. The device has the correct class, duplicate it to the + interface. */ + swar -> ux_host_class_swar_interface -> ux_interface_class = swar -> ux_host_class_swar_device -> ux_device_class ; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_swar_deactivate.c b/common/usbx_host_classes/src/ux_host_class_swar_deactivate.c new file mode 100644 index 0000000..4f3adda --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_swar_deactivate.c @@ -0,0 +1,141 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_swar.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_swar_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the swar has been */ +/* removed from the bus either directly or indirectly. The bulk in\out */ +/* pipes will be destroyed and the instanced removed. */ +/* */ +/* INPUT */ +/* */ +/* command Swar class command pointer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy the class instance */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort endpoint transfer */ +/* _ux_utility_memory_free Free memory block */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_delete Delete protection semaphore */ +/* _ux_utility_thread_schedule_other Schedule other threads */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_swar_entry Entry of swar class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_swar_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_SWAR *swar; +UINT status; + + + /* Get the instance for this class. */ + swar = (UX_HOST_CLASS_SWAR *) command -> ux_host_class_command_instance; + + /* The swar is being shut down. */ + swar -> ux_host_class_swar_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&swar -> ux_host_class_swar_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, swar, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* We need to abort transactions on the bulk Out pipe. */ + _ux_host_stack_endpoint_transfer_abort(swar -> ux_host_class_swar_bulk_out_endpoint); + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(swar -> ux_host_class_swar_bulk_in_endpoint); + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(swar -> ux_host_class_swar_class, (VOID *) swar); + + /* Destroy the semaphore. */ + _ux_utility_semaphore_delete(&swar -> ux_host_class_swar_semaphore); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, swar -> ux_host_class_swar_class, (VOID *) swar); + } + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_SWAR_DEACTIVATE, swar, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_UNREGISTER(swar); + + /* Free the swar instance memory. */ + _ux_utility_memory_free(swar); + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_swar_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_swar_endpoints_get.c new file mode 100644 index 0000000..819aeae --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_swar_endpoints_get.c @@ -0,0 +1,164 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_swar.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_swar_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function search for the handle of the bulk out and bulk in */ +/* endpoints. The Sierra Wireless USB device has multiple interfaces. */ +/* We first need to find the interface which uses Bulk endpoints to */ +/* carry data. */ +/* */ +/* INPUT */ +/* */ +/* swar Pointer to swar class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* */ +/* CALLED BY */ +/* */ +/* _ux_host_class_swar_activate Activate swar class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_swar_endpoints_get(UX_HOST_CLASS_SWAR *swar) +{ + +UINT status; +UX_ENDPOINT *endpoint; +UINT endpoint_index; + + /* Search the bulk OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < swar -> ux_host_class_swar_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get interface endpoint. */ + status = _ux_host_stack_interface_endpoint_get(swar -> ux_host_class_swar_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the OUT direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_OUT; + + /* We have found the bulk endpoint, save it. */ + swar -> ux_host_class_swar_bulk_out_endpoint = endpoint; + break; + } + } + } + + /* The bulk out endpoint is mandatory. */ + if (swar -> ux_host_class_swar_bulk_out_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, swar, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Search the bulk IN endpoint. It is attached to the interface container. */ + + for (endpoint_index = 0; endpoint_index < swar -> ux_host_class_swar_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get the endpoint handle. */ + status = _ux_host_stack_interface_endpoint_get(swar -> ux_host_class_swar_interface, endpoint_index, &endpoint); + + /* Check the completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is bulk and IN. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_IN) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_BULK_ENDPOINT)) + { + + /* This transfer_request always have the IN direction. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_type = UX_REQUEST_IN; + + /* We have found the bulk endpoint, save it. */ + swar -> ux_host_class_swar_bulk_in_endpoint = endpoint; + break; + } + } + } + + /* The bulk in endpoint is mandatory. */ + if (swar -> ux_host_class_swar_bulk_in_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, swar, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* All endpoints have been mounted. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_swar_entry.c b/common/usbx_host_classes/src/ux_host_class_swar_entry.c new file mode 100644 index 0000000..b4a754a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_swar_entry.c @@ -0,0 +1,120 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_swar.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_swar_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the swar class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* swar on the bus or when the USB swar is removed. */ +/* */ +/* INPUT */ +/* */ +/* command swar class command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_swar_activate Activate swar class */ +/* _ux_host_class_swar_deactivate Deactivate swar class */ +/* */ +/* CALLED BY */ +/* */ +/* Data pump Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_swar_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if(((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_PIDVID) && + (command -> ux_host_class_command_pid == UX_HOST_CLASS_SWAR_PRODUCT_ID) && + (command -> ux_host_class_command_vid == UX_HOST_CLASS_SWAR_VENDOR_ID ))) + return(UX_SUCCESS); + else + return(UX_NO_CLASS_MATCH); + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_swar_activate(command); + return(status); + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_swar_deactivate(command); + return(status); + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_FUNCTION_NOT_SUPPORTED); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_swar_ioctl.c b/common/usbx_host_classes/src/ux_host_class_swar_ioctl.c new file mode 100644 index 0000000..af31172 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_swar_ioctl.c @@ -0,0 +1,127 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_swar.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_swar_ioctl PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the ioctl entry point for the application to */ +/* configure the Swar device. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* swar Pointer to swar class */ +/* ioctl_function ioctl function */ +/* parameter pointer to structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort transfer */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_swar_ioctl(UX_HOST_CLASS_SWAR *swar, ULONG ioctl_function, + VOID *parameter) +{ + +UINT status; + + UX_PARAMETER_NOT_USED(parameter); + + /* The command request will tell us we need to do here. */ + switch (ioctl_function) + { + + case UX_HOST_CLASS_SWAR_IOCTL_ABORT_IN_PIPE : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_SWAR_IOCTL_ABORT_IN_PIPE, swar, swar -> ux_host_class_swar_bulk_in_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(swar -> ux_host_class_swar_bulk_in_endpoint); + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + case UX_HOST_CLASS_SWAR_IOCTL_ABORT_OUT_PIPE : + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_SWAR_IOCTL_ABORT_OUT_PIPE, swar, swar -> ux_host_class_swar_bulk_out_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to abort transactions on the bulk Out pipe. */ + _ux_host_stack_endpoint_transfer_abort(swar -> ux_host_class_swar_bulk_out_endpoint); + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Function not supported. Return an error. */ + status = UX_FUNCTION_NOT_SUPPORTED; + break; + } + + /* Return status to caller. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_swar_read.c b/common/usbx_host_classes/src/ux_host_class_swar_read.c new file mode 100644 index 0000000..a57ed4c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_swar_read.c @@ -0,0 +1,205 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_swar.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_swar_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the swar interface. The call is */ +/* blocking and only returns when there is either an error or when */ +/* the transfer is complete. */ +/* */ +/* INPUT */ +/* */ +/* swar Pointer to swar class */ +/* data_pointer Pointer to buffer */ +/* requested_length Requested data read */ +/* actual_length Actual data read */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify the class instance */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_swar_read(UX_HOST_CLASS_SWAR *swar, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_SWAR_READ, swar, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_swar_name, (VOID *) swar) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, swar, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&swar -> ux_host_class_swar_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* Start by resetting the actual length of the transfer to zero. */ + *actual_length = 0; + + /* Get the pointer to the bulk in endpoint in the transfer_request. */ + transfer_request = &swar -> ux_host_class_swar_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Perform a transfer on the bulk in endpoint until either the transfer is + completed or until there is an error. */ + while (requested_length) + { + + /* Program the maximum authorized length for this transfer request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer_request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_HOST_CLASS_SWAR_CLASS_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer request in case some data was actually received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + + /* There was a non transfer error, no partial transfer to be checked. */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be received. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually received and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + + /* Return success to caller. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to receive. */ + requested_length -= transfer_request_length; + } + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_swar_reception_callback.c b/common/usbx_host_classes/src/ux_host_class_swar_reception_callback.c new file mode 100644 index 0000000..a1807fa --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_swar_reception_callback.c @@ -0,0 +1,143 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_swar.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_swar_reception_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the callback from the USBX transfer functions, */ +/* it is called when a full or partial transfer has been done for a */ +/* bulk in transfer. It calls back the application. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_swar_reception_callback (UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_SWAR *swar; +UX_HOST_CLASS_SWAR_RECEPTION *swar_reception; + + /* Get the class instance for this transfer request. */ + swar = (UX_HOST_CLASS_SWAR *) transfer_request -> ux_transfer_request_class_instance; + + /* Get the pointer to the acm reception structure. */ + swar_reception = swar -> ux_host_class_swar_reception; + + /* Check the state of the transfer. If there is an error, we do not proceed with this report. */ + if (transfer_request -> ux_transfer_request_completion_code != UX_SUCCESS) + { + + /* The reception is stopped. */ + swar_reception -> ux_host_class_swar_reception_state = UX_HOST_CLASS_SWAR_RECEPTION_STATE_STOPPED; + + /* We do not proceed. */ + return; + + } + + /* And move to the next reception buffer. Check if we are at the end of the application buffer. */ + if (swar_reception -> ux_host_class_swar_reception_data_head + swar_reception -> ux_host_class_swar_reception_block_size >= + swar_reception -> ux_host_class_swar_reception_data_buffer + swar_reception -> ux_host_class_swar_reception_data_buffer_size) + { + + /* We are at the end of the buffer. Move back to the beginning if we have space available. */ + if (swar_reception -> ux_host_class_swar_reception_data_tail == swar_reception -> ux_host_class_swar_reception_data_buffer) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_BUFFER_OVERFLOW); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_BUFFER_OVERFLOW, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We have an overflow. We cannot continue. Report to the application. */ + swar_reception -> ux_host_class_swar_reception_callback(swar, UX_BUFFER_OVERFLOW, UX_NULL, 0); + + /* And stop the transfer in progress flag. */ + swar_reception -> ux_host_class_swar_reception_state = UX_HOST_CLASS_SWAR_RECEPTION_STATE_STOPPED; + + return; + } + else + + /* Program the head to be at the beginning of the application buffer. */ + swar_reception -> ux_host_class_swar_reception_data_head = swar_reception -> ux_host_class_swar_reception_data_buffer; + + } + else + + /* Program the head to be after the current buffer. */ + swar_reception -> ux_host_class_swar_reception_data_head += swar_reception -> ux_host_class_swar_reception_block_size; + + + /* We need to report this transfer to the application. */ + swar_reception -> ux_host_class_swar_reception_callback(swar, + transfer_request -> ux_transfer_request_completion_code, + transfer_request -> ux_transfer_request_data_pointer, + transfer_request -> ux_transfer_request_actual_length); + + /* Arm another transfer. */ + _ux_host_stack_transfer_request(transfer_request); + + /* There is no status to be reported back to the stack. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_swar_reception_start.c b/common/usbx_host_classes/src/ux_host_class_swar_reception_start.c new file mode 100644 index 0000000..650a31a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_swar_reception_start.c @@ -0,0 +1,129 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_swar.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_swar_reception_start PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a reception with the Sierra modem. This way */ +/* allows for non blocking calls based on a packet orientated round */ +/* robbin buffer. When a packet is fully or partially received, an */ +/* application callback function is invoked and a new transfer request */ +/* is rescheduled. */ +/* */ +/* INPUT */ +/* */ +/* swar Pointer to swar class */ +/* swar_reception Pointer to reception struct */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify the class instance */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_swar_reception_start (UX_HOST_CLASS_SWAR *swar, + UX_HOST_CLASS_SWAR_RECEPTION *swar_reception) +{ + +UX_TRANSFER *transfer_request; +UINT status; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_SWAR_RECEPTION_START, swar, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_swar_name, (VOID *) swar) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, swar, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Start by aligning the head and tail of buffers to the same address supplied by the application. */ + swar_reception -> ux_host_class_swar_reception_data_head = swar_reception -> ux_host_class_swar_reception_data_buffer; + swar_reception -> ux_host_class_swar_reception_data_tail = swar_reception -> ux_host_class_swar_reception_data_buffer; + + /* Get the pointer to the bulk in endpoint in the transfer_request. */ + transfer_request = &swar -> ux_host_class_swar_bulk_in_endpoint -> ux_endpoint_transfer_request; + + /* Initialize the transfer request. */ + transfer_request -> ux_transfer_request_class_instance = (VOID *) swar; + transfer_request -> ux_transfer_request_data_pointer = swar_reception -> ux_host_class_swar_reception_data_head; + transfer_request -> ux_transfer_request_requested_length = swar_reception -> ux_host_class_swar_reception_block_size; + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_swar_reception_callback; + + /* Save the acm reception structure in the acm structure. */ + swar -> ux_host_class_swar_reception = swar_reception; + + /* And declare we have a transfer in progress. */ + swar_reception -> ux_host_class_swar_reception_state = UX_HOST_CLASS_SWAR_RECEPTION_STATE_STARTED; + + /* Arm a first transfer on the bulk in endpoint. There is a callback to this function so we return to the caller + right away. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* We do not know if the first transfer was successful yet. If the status is not OK, we need to stop the transfer + in progress flag. */ + if (status != UX_SUCCESS) + swar_reception -> ux_host_class_swar_reception_state = UX_HOST_CLASS_SWAR_RECEPTION_STATE_STOPPED; + + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_swar_reception_stop.c b/common/usbx_host_classes/src/ux_host_class_swar_reception_stop.c new file mode 100644 index 0000000..2eadac6 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_swar_reception_stop.c @@ -0,0 +1,110 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_swar.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_swar_reception_stop PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a reception with the Sierra modem. This way */ +/* allows for non blocking calls based on a packet orientated round */ +/* robbin buffer. When a packet is fully or partially received, an */ +/* application callback function is invoked and a new transfer request */ +/* is rescheduled. */ +/* */ +/* INPUT */ +/* */ +/* swar Pointer to swar class */ +/* swar_reception Pointer to reception struct */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify the class instance */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort transfer */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_swar_reception_stop (UX_HOST_CLASS_SWAR *swar, + UX_HOST_CLASS_SWAR_RECEPTION *swar_reception) +{ + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_SWAR_RECEPTION_STOP, swar, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_swar_name, (VOID *) swar) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, swar, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Check if we do have transfers for this application. If none, nothing to do. */ + if (swar_reception -> ux_host_class_swar_reception_state == UX_HOST_CLASS_SWAR_RECEPTION_STATE_STOPPED) + return(UX_SUCCESS); + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(swar -> ux_host_class_swar_bulk_in_endpoint); + + /* Declare the reception stopped. */ + swar_reception -> ux_host_class_swar_reception_state = UX_HOST_CLASS_SWAR_RECEPTION_STATE_STOPPED; + + /* This function never really fails. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_swar_write.c b/common/usbx_host_classes/src/ux_host_class_swar_write.c new file mode 100644 index 0000000..b7f2424 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_swar_write.c @@ -0,0 +1,207 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Host Sierra Wireless AR module class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_swar.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_swar_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes to the swar interface. The call is blocking */ +/* and only returns when there is either an error or when the transfer */ +/* is complete. */ +/* */ +/* INPUT */ +/* */ +/* swar Pointer to swar class */ +/* data_pointer Pointer to data to write */ +/* requested_length Length of data to write */ +/* actual_length Actual length of data written */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify the class instance */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_semaphore_get Get protection semaphore */ +/* _ux_utility_semaphore_put Release protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_swar_write(UX_HOST_CLASS_SWAR *swar, UCHAR * data_pointer, + ULONG requested_length, ULONG *actual_length) +{ + +UX_TRANSFER *transfer_request; +UINT status; +ULONG transfer_request_length; + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_SWAR_WRITE, swar, data_pointer, requested_length, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* Ensure the instance is valid. */ + if(_ux_host_stack_class_instance_verify((UCHAR *) _ux_system_host_class_swar_name, (VOID *) swar) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, swar, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&swar -> ux_host_class_swar_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* Start by resetting the actual length of the transfer. */ + *actual_length = 0; + + /* Get the pointer to the bulk out endpoint transfer request. */ + transfer_request = &swar -> ux_host_class_swar_bulk_out_endpoint -> ux_endpoint_transfer_request; + + /* Perform a transfer on the bulk out endpoint until either the transfer is + completed or when there is an error. */ + do + { + + /* Program the maximum authorized length for this transfer_request. */ + if (requested_length > transfer_request -> ux_transfer_request_maximum_length) + transfer_request_length = transfer_request -> ux_transfer_request_maximum_length; + else + transfer_request_length = requested_length; + + /* Initialize the transfer_request. */ + transfer_request -> ux_transfer_request_data_pointer = data_pointer; + transfer_request -> ux_transfer_request_requested_length = transfer_request_length; + + /* Perform the transfer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* If the transfer is successful, we need to wait for the transfer request to be completed. */ + if (status == UX_SUCCESS) + { + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, UX_HOST_CLASS_SWAR_CLASS_TRANSFER_TIMEOUT); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* Update the length of the actual data transferred. We do this after the + abort of the transfer_request in case some data actually went out. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + + /* Set the completion code. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* There was an error, return to the caller. */ + return(UX_TRANSFER_TIMEOUT); + } + } + else + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + + /* There was a non transfer error, no partial transfer to be checked */ + return(status); + } + + /* Update the length of the transfer. Normally all the data has to be sent. */ + *actual_length += transfer_request -> ux_transfer_request_actual_length; + + /* Check for completion of transfer. If the transfer is partial, return to caller. + The transfer is marked as successful but the caller will need to check the length + actually sent and determine if a partial transfer is OK. */ + if (transfer_request_length != transfer_request -> ux_transfer_request_actual_length) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + + /* Return success. */ + return(UX_SUCCESS); + } + + /* Update the data pointer for next transfer. */ + data_pointer += transfer_request_length; + + /* Update what is left to send out. */ + requested_length -= transfer_request_length; + + } while (requested_length != 0); + + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&swar -> ux_host_class_swar_semaphore); + + /* We get here when all the transfers went through without errors. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_activate.c b/common/usbx_host_classes/src/ux_host_class_video_activate.c new file mode 100644 index 0000000..440c4ca --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_activate.c @@ -0,0 +1,200 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + +UCHAR _ux_system_class_video_interface_descriptor_structure[] = {1,1,1,1,1,1,1,1}; +UCHAR _ux_system_class_video_input_terminal_descriptor_structure[] = {1,1,1,1,2,1,1}; +UCHAR _ux_system_class_video_input_header_descriptor_structure[] = {1,1,1,1,2,1,1,1,1,1,1,1}; +UCHAR _ux_system_class_video_processing_unit_descriptor_structure[] = {1,1,1,1,1,2,1,1}; +UCHAR _ux_system_class_video_streaming_interface_descriptor_structure[] = {1,1,1,1,1,1}; +UCHAR _ux_system_class_video_streaming_endpoint_descriptor_structure[] = {1,1,1,1,1,1}; +UCHAR _ux_system_class_video_frame_descriptor_structure[] = {1,1,1,1,1,2,2,4,4,4,4,1}; + +UCHAR _ux_system_host_class_video_name[] = "ux_host_class_video"; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function activates the video class. It may be called twice by */ +/* the same device if there is a video control interface to this */ +/* device. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_video_configure Configure the video class */ +/* _ux_host_class_video_descriptor_get Get video descriptor */ +/* _ux_host_class_video_input_terminal_get */ +/* Get input terminal */ +/* _ux_host_class_video_input_format_get Get input format */ +/* _ux_host_class_video_control_list_get Get controls */ +/* _ux_host_stack_class_instance_create Create class instance */ +/* _ux_host_stack_class_instance_destroy Destroy class instance */ +/* _ux_utility_memory_allocate Allocate a memory block */ +/* _ux_utility_memory_free Free a memory block */ +/* _ux_utility_semaphore_create Create protection semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_activate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_INTERFACE *interface; +UX_HOST_CLASS_VIDEO *video; +UINT status; + + + /* The video is always activated by the interface descriptor and not the + device descriptor. */ + interface = (UX_INTERFACE *) command -> ux_host_class_command_container; + + /* Check the subclass of the new device. If it is a Video Control Interface, + we don't need to create an instance of this function. When we get the streaming interface, + we will search the video control interface for the device. */ + if (interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_VIDEO_SUBCLASS_CONTROL) + return(UX_SUCCESS); + + /* Obtain memory for this class instance. */ + video = (UX_HOST_CLASS_VIDEO *) _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HOST_CLASS_VIDEO)); + if (video == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Store the class container into this instance. */ + video -> ux_host_class_video_class = command -> ux_host_class_command_class_ptr; + + /* Store the interface container into the video class instance. */ + video -> ux_host_class_video_streaming_interface = interface; + + /* Store the device container into the video class instance. */ + video -> ux_host_class_video_device = interface -> ux_interface_configuration -> ux_configuration_device; + + /* This instance of the device must also be stored in the interface container. */ + interface -> ux_interface_class_instance = (VOID *) video; + + /* Create this class instance. */ + status = _ux_host_stack_class_instance_create(video -> ux_host_class_video_class, (VOID *) video); + + /* Configure the video. */ + status = _ux_host_class_video_configure(video); + + /* Get the video descriptor (all the class specific stuff) and memorize them + as we will need these descriptors to change settings. */ + if (status == UX_SUCCESS) + status = _ux_host_class_video_descriptor_get(video); + + /* Locate the video device streaming terminal. */ + if (status == UX_SUCCESS) + status = _ux_host_class_video_input_terminal_get(video); + + /* In the input terminal streaming interface get the number of formats supported. */ + if (status == UX_SUCCESS) + status = _ux_host_class_video_input_format_get(video); + + /* Get video controls. */ + if (status == UX_SUCCESS) + status = _ux_host_class_video_control_list_get(video); + + /* Create the semaphore to protect multiple threads from accessing the same + video instance. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&video -> ux_host_class_video_semaphore, "ux_video_semaphore", 1); + if (status != UX_SUCCESS) + status = UX_SEMAPHORE_ERROR; + } + + if (status == UX_SUCCESS) + { + + /* Mark the video as live now. */ + video -> ux_host_class_video_state = UX_HOST_CLASS_INSTANCE_LIVE; + + /* If all is fine and the device is mounted, we may need to inform the application + if a function has been programmed in the system structure. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Call system change function. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_INSERTION, video -> ux_host_class_video_class, (VOID *) video); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_VIDEO_ACTIVATE, video, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + UX_TRACE_OBJECT_REGISTER(UX_TRACE_HOST_OBJECT_TYPE_INTERFACE, video, 0, 0, 0) + + /* Return success. */ + return(UX_SUCCESS); + } + + /* There was error, free resources. */ + + /* The last resource, video -> ux_host_class_video_semaphore is not created or created error, + no need to free. */ + + /* Destroy the class instance. */ + _ux_host_stack_class_instance_destroy(video -> ux_host_class_video_class, (VOID *) video); + + /* This instance of the device must also be cleared in the interface container. */ + interface -> ux_interface_class_instance = UX_NULL; + + /* Free instance memory. */ + _ux_utility_memory_free(video); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_alternate_setting_locate.c b/common/usbx_host_classes/src/ux_host_class_video_alternate_setting_locate.c new file mode 100644 index 0000000..279edaa --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_alternate_setting_locate.c @@ -0,0 +1,155 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_alternate_setting_locate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function finds the alternate setting for the specific format. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* alternate_setting Pointer to located alternate */ +/* setting */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler Log system error */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_alternate_setting_locate(UX_HOST_CLASS_VIDEO *video, UINT max_payload_size, UINT *alternate_setting) +{ + +UX_CONFIGURATION *configuration; +UX_INTERFACE *interface; +UX_ENDPOINT *endpoint; +UINT streaming_interface; +UINT payload_size; +UINT current_payload_size = 0; +UINT alternate_setting_found; + + + configuration = video -> ux_host_class_video_streaming_interface -> ux_interface_configuration; + interface = configuration -> ux_configuration_first_interface; + streaming_interface = video -> ux_host_class_video_streaming_interface -> ux_interface_descriptor.bInterfaceNumber; + + alternate_setting_found = UX_FALSE; + + /* Scan all interfaces. */ + while (interface != UX_NULL) + { + + /* Search for the streaming interface with a endpoint. */ + if ((interface -> ux_interface_descriptor.bInterfaceNumber == streaming_interface) && + (interface -> ux_interface_first_endpoint != 0)) + { + + /* Get the max packet size of the endpoint. */ + endpoint = interface -> ux_interface_first_endpoint; + payload_size = (endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_PACKET_SIZE_MASK) * + (((endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK) >> + UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT) + 1); + + /* Check if the payload size is equal or greater than the required payload size. */ + if (payload_size >= max_payload_size) + { + + /* Check if we have found any alternate settings yet. */ + if(alternate_setting_found == UX_FALSE) + { + + /* Save the current payload size and mark the found flag. */ + alternate_setting_found = UX_TRUE; + current_payload_size = payload_size; + + /* Save the found alternate setting number. */ + *alternate_setting = interface -> ux_interface_descriptor.bAlternateSetting; + } + else + { + + /* Check if the payload size is smaller. */ + if (payload_size < current_payload_size) + { + + /* Smaller payload size found, select the current setting. */ + current_payload_size = payload_size; + + /* Save the found alternate setting number. */ + *alternate_setting = interface -> ux_interface_descriptor.bAlternateSetting; + } + } + } + } + + /* Move to next interface. */ + interface = interface -> ux_interface_next_interface; + } + + /* Check if we found the alternate setting. */ + if (alternate_setting_found) + { + + /* Return successful completion. */ + return(UX_SUCCESS); + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_TYPE); + + /* We get here when either the report descriptor has a problem or we could + not find the right video device. */ + return(UX_HOST_CLASS_VIDEO_WRONG_TYPE); +} diff --git a/common/usbx_host_classes/src/ux_host_class_video_channel_start.c b/common/usbx_host_classes/src/ux_host_class_video_channel_start.c new file mode 100644 index 0000000..d0e1f39 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_channel_start.c @@ -0,0 +1,268 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_channel_start PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts the video channel. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* channel_parameter Pointer to video channel */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_video_alternate_setting_locate */ +/* Search alternate setting */ +/* _ux_host_stack_interface_setting_select */ +/* Select alternate setting */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_long_get Get 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_channel_start(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_PARAMETER_CHANNEL *video_parameter) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +UCHAR *control_buffer; +UINT alternate_setting; +UX_CONFIGURATION *configuration; +UX_INTERFACE *interface; +UX_ENDPOINT *endpoint; +ULONG endpoint_index; +UINT streaming_interface; +UINT max_payload_size; + + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &video -> ux_host_class_video_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Get the interface number of the video streaming interface. */ + streaming_interface = video -> ux_host_class_video_streaming_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Need to allocate memory for the control_buffer. */ + control_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_VIDEO_PROBE_COMMIT_LENGTH); + if (control_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return error. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Check the result, did we find the alternate setting ? */ + if (status == UX_SUCCESS) + { + + *(control_buffer + UX_HOST_CLASS_VIDEO_PROBE_COMMIT_FORMAT_INDEX) = (UCHAR)video_parameter -> ux_host_class_video_parameter_format_requested; + *(control_buffer + UX_HOST_CLASS_VIDEO_PROBE_COMMIT_FRAME_INDEX) = (UCHAR)video_parameter -> ux_host_class_video_parameter_frame_requested; + _ux_utility_long_put(control_buffer + UX_HOST_CLASS_VIDEO_PROBE_COMMIT_FRAME_INTERVAL, + video_parameter -> ux_host_class_video_parameter_frame_interval_requested); + + /* Create a transfer request for the GET_CUR_buffer request. */ + transfer_request -> ux_transfer_request_data_pointer = control_buffer; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_VIDEO_PROBE_COMMIT_LENGTH; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_VIDEO_SET_CUR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_VIDEO_VS_PROBE_CONTROL << 8; + transfer_request -> ux_transfer_request_index = streaming_interface; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer. Buffer may not be all what we asked for. */ + if (status == UX_SUCCESS) + { + + + /* Create a transfer request for the SET_CUR_buffer request. */ + transfer_request -> ux_transfer_request_data_pointer = control_buffer; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_VIDEO_PROBE_COMMIT_LENGTH; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_VIDEO_GET_CUR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_VIDEO_VS_PROBE_CONTROL << 8; + transfer_request -> ux_transfer_request_index = streaming_interface; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer. */ + if (status == UX_SUCCESS) + { + + /* We did the GET_CUR and SET_CUR for Probe Control. Now we can commit to the bandwidth. */ + /* Create a transfer request for the SET_CUR_buffer request. */ + transfer_request -> ux_transfer_request_data_pointer = control_buffer; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_VIDEO_PROBE_COMMIT_LENGTH; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_VIDEO_SET_CUR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_VIDEO_VS_COMMIT_CONTROL << 8; + transfer_request -> ux_transfer_request_index = streaming_interface; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer. */ + if (status == UX_SUCCESS) + { + + /* Check if user has request specific bandwidth selection. */ + if (video_parameter -> ux_host_class_video_parameter_channel_bandwidth_selection == 0) + { + + /* Get the max payload transfer size returned from video device. */ + max_payload_size = _ux_utility_long_get(control_buffer + UX_HOST_CLASS_VIDEO_PROBE_COMMIT_MAX_PAYLOAD_TRANSFER_SIZE); + } + else + { + + /* Set the max payload transfer size to the user requested one. */ + max_payload_size = video_parameter -> ux_host_class_video_parameter_channel_bandwidth_selection; + } + + /* Search for the non zero alternate setting of the video stream. */ + status = _ux_host_class_video_alternate_setting_locate(video, max_payload_size, &alternate_setting); + + /* Now the Commit has been done, the alternate setting can be requested. */ + /* We found the alternate setting for the sampling values demanded, now we need + to search its container. */ + configuration = video -> ux_host_class_video_streaming_interface -> ux_interface_configuration; + interface = configuration -> ux_configuration_first_interface; + + + /* Scan all interfaces. */ + while (interface != UX_NULL) + { + + /* We search for both the right interface and alternate setting. */ + if ((interface -> ux_interface_descriptor.bInterfaceNumber == streaming_interface) && + (interface -> ux_interface_descriptor.bAlternateSetting == alternate_setting)) + { + + /* We have found the right interface/alternate setting combination + The stack will select it for us. */ + status = _ux_host_stack_interface_setting_select(interface); + + /* If the alternate setting for the streaming interface could be selected, we memorize it. */ + if (status == UX_SUCCESS) + { + + /* Memorize the interface. */ + video -> ux_host_class_video_streaming_interface = interface; + + /* We need to research the isoch endpoint now. */ + for (endpoint_index = 0; endpoint_index < interface -> ux_interface_descriptor.bNumEndpoints; endpoint_index++) + { + + /* Get the list of endpoints one by one. */ + status = _ux_host_stack_interface_endpoint_get(video -> ux_host_class_video_streaming_interface, + endpoint_index, &endpoint); + + /* Check completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is ISOCH, regardless of the direction. */ + if ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_ISOCHRONOUS_ENDPOINT) + { + + /* We have found the isoch endpoint, save it. */ + video -> ux_host_class_video_isochronous_endpoint = endpoint; + + /* Free all used resources. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return successful completion. */ + return(UX_SUCCESS); + } + } + } + } + } + + /* Move to next interface. */ + interface = interface -> ux_interface_next_interface; + } + } + } + } + } + /* Free all used resources. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_configure.c b/common/usbx_host_classes/src/ux_host_class_video_configure.c new file mode 100644 index 0000000..e9cca7b --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_configure.c @@ -0,0 +1,179 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_configure PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the USBX stack to do a SET_CONFIGURATION to */ +/* the device. Once the device is configured, its interface(s) will */ +/* be activated. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_configuration_interface_get */ +/* Get interface */ +/* _ux_host_stack_device_configuration_get */ +/* Get configuration */ +/* _ux_host_stack_device_configuration_select */ +/* Select configuration */ +/* _ux_system_error_handler Log system error */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_configure(UX_HOST_CLASS_VIDEO *video) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_INTERFACE *interface; +UX_DEVICE *parent_device; +ULONG interface_number; + + + /* If the device has been configured already, we don't need to do it + again. */ + if (video -> ux_host_class_video_device -> ux_device_state == UX_DEVICE_CONFIGURED) + return(UX_SUCCESS); + + /* An video device normally has one configuration. So retrieve the 1st configuration + only. */ + status = _ux_host_stack_device_configuration_get(video -> ux_host_class_video_device, 0, &configuration); + if (status != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONFIGURATION_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONFIGURATION_HANDLE_UNKNOWN, video -> ux_host_class_video_device, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONFIGURATION_HANDLE_UNKNOWN); + + } + /* Check the video power source and check the parent power source for + incompatible connections. */ + if (video -> ux_host_class_video_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED) + { + + /* Get parent device. */ + parent_device = video -> ux_host_class_video_device -> ux_device_parent; + + /* If the device is NULL, the parent is the root video and we don't have to worry + if the parent is not the root video, check for its power source. */ + if ((parent_device != UX_NULL) && (parent_device -> ux_device_power_source == UX_DEVICE_BUS_POWERED)) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CONNECTION_INCOMPATIBLE); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONNECTION_INCOMPATIBLE, video, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONNECTION_INCOMPATIBLE); + } + } + + /* We have the valid configuration. Ask the USBX stack to set this configuration */ + status = _ux_host_stack_device_configuration_select(configuration); + + /* Start with interface number 0. */ + interface_number = 0; + + /* We only need to retrieve the video streaming interface. */ + do + { + + /* Pickup interface. */ + status = _ux_host_stack_configuration_interface_get(configuration, (UINT) interface_number, 0, &interface); + + /* Check completion status. */ + if (status == UX_SUCCESS) + { + + /* Check the type of interface we have found - is it streaming? */ + if (interface -> ux_interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_VIDEO_SUBCLASS_STREAMING) + { + + video -> ux_host_class_video_streaming_interface = interface; + video -> ux_host_class_video_streaming_interface -> ux_interface_class_instance = (VOID *)video; + break; + } + } + + /* Move to next interface. */ + interface_number++; + } while(status == UX_SUCCESS); + + /* After we have parsed the video interfaces, ensure the streaming interfaces is resent. */ + if (video -> ux_host_class_video_streaming_interface == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_INTERFACE_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_INTERFACE_HANDLE_UNKNOWN, interface, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We get here when we could not locate the interface(s) handle */ + return(UX_INTERFACE_HANDLE_UNKNOWN); + } + + return(UX_SUCCESS); + +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_control_get.c b/common/usbx_host_classes/src/ux_host_class_video_control_get.c new file mode 100644 index 0000000..26602a3 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_control_get.c @@ -0,0 +1,212 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_control_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the static values for a single video control */ +/* on either the master channel or a specific channel. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* video_control Pointer to video control */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_short_get Read 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_control_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_CONTROL *video_control) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +UCHAR * control_buffer; + + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_video_name, (VOID *) video) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, video, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &video -> ux_host_class_video_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the control buffer. */ + control_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 2); + if (control_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return an error. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + + /* Something went wrong. */ + return(status); + + /* Create a transfer request for the GET_MIN request. */ + transfer_request -> ux_transfer_request_data_pointer = control_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_VIDEO_GET_MIN; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = (video_control -> ux_host_class_video_control << 8); + transfer_request -> ux_transfer_request_index = video -> ux_host_class_video_control_interface_number | (video -> ux_host_class_video_feature_unit_id << 8); + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire control buffer returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 2)) + { + + /* Update the MIN static value for the caller. */ + video_control -> ux_host_class_video_control_min = (LONG)(SHORT)_ux_utility_short_get(control_buffer); + } + else + { + + /* Free the previous control buffer. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + } + + /* Create a transfer request for the GET_MAX request. */ + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_VIDEO_GET_MAX; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire control buffer returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 2)) + { + + /* Update the MAX static value for the caller. */ + video_control -> ux_host_class_video_control_max = (LONG)(SHORT)_ux_utility_short_get(control_buffer); + } + else + { + + /* Free the previous control buffer. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + } + + /* Create a transfer request for the GET_RES request. */ + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_VIDEO_GET_RES; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire control buffer returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 2)) + { + + /* Update the RES static value for the caller. */ + video_control -> ux_host_class_video_control_res = (LONG)(SHORT)_ux_utility_short_get(control_buffer); + } + + /* Free all used resources. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_control_list_get.c b/common/usbx_host_classes/src/ux_host_class_video_control_list_get.c new file mode 100644 index 0000000..184324e --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_control_list_get.c @@ -0,0 +1,190 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_control_list_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the controls for the video device. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_system_error_handler Log system error */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_control_list_get(UX_HOST_CLASS_VIDEO *video) +{ + +UCHAR *descriptor; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UX_HOST_CLASS_VIDEO_PROCESSING_UNIT_DESCRIPTOR processing_unit_descriptor; +ULONG total_descriptor_length; +ULONG descriptor_length; +ULONG descriptor_type; +ULONG descriptor_subtype; +ULONG interface_found; + + + /* Get the descriptor to the selected format. */ + descriptor = video -> ux_host_class_video_configuration_descriptor; + total_descriptor_length = video -> ux_host_class_video_configuration_descriptor_length; + + /* Haven't found it yet. */ + interface_found = UX_FALSE; + + /* Scan the descriptor for the Video Streaming interface. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Process relative to descriptor type. */ + switch (descriptor_type) + { + + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &interface_descriptor); + + /* Ensure we have the correct interface for Video Control. */ + if ((interface_descriptor.bInterfaceClass == UX_HOST_CLASS_VIDEO_CLASS) && + (interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_VIDEO_SUBCLASS_CONTROL)) + { + + /* Mark we have found it. */ + interface_found = UX_TRUE; + + /* Get the interface number of this descriptor and save it in the video + instance. This will be useful to program the video controls. */ + video -> ux_host_class_video_control_interface_number = interface_descriptor.bInterfaceNumber; + } + else + { + + /* Haven't found it. */ + interface_found = UX_FALSE; + } + break; + + + case UX_HOST_CLASS_VIDEO_CS_INTERFACE: + + /* First make sure we have found the correct generic interface descriptor. */ + if ((interface_found == UX_TRUE) && (descriptor_subtype == UX_HOST_CLASS_VIDEO_VC_PROCESSING_UNIT)) + { + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_video_input_terminal_descriptor_structure, + UX_HOST_CLASS_VIDEO_PROCESSING_UNIT_DESCRIPTOR_ENTRIES, (UCHAR *) &processing_unit_descriptor); + + video -> ux_host_class_video_feature_unit_id = processing_unit_descriptor.bUnitID; + + /* We are done here. */ + return(UX_SUCCESS); + } + + break; + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_TYPE); + + /* We get here when either the report descriptor has a problem or we could + not find the right video device. */ + return(UX_HOST_CLASS_VIDEO_WRONG_TYPE); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_control_value_get.c b/common/usbx_host_classes/src/ux_host_class_video_control_value_get.c new file mode 100644 index 0000000..6e74320 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_control_value_get.c @@ -0,0 +1,172 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_control_value_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the current values for a single video control.*/ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* video_control Pointer to video control */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_short_get Read 16-bit value */ +/* _ux_system_error_handler Log system error */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_control_value_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_CONTROL *video_control) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +UCHAR * control_buffer; + + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_video_name, (VOID *) video) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, video, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &video -> ux_host_class_video_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the control buffer. */ + control_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 2); + if (control_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return an error. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + + /* Something went wrong. */ + return(status); + + /* Create a transfer request for the GET_MIN request. */ + transfer_request -> ux_transfer_request_data_pointer = control_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_VIDEO_GET_CUR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = (video_control -> ux_host_class_video_control << 8); + transfer_request -> ux_transfer_request_index = video -> ux_host_class_video_control_interface_number | (video -> ux_host_class_video_feature_unit_id << 8); + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire control buffer returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == 2)) + { + + /* Update the MIN static value for the caller. */ + video_control -> ux_host_class_video_control_cur = (LONG)(SHORT)_ux_utility_short_get(control_buffer); + } + else + { + + /* Free the previous control buffer. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + } + + /* Free all used resources. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_control_value_set.c b/common/usbx_host_classes/src/ux_host_class_video_control_value_set.c new file mode 100644 index 0000000..e5eaa5c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_control_value_set.c @@ -0,0 +1,168 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_control_value_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function updates the current values for a single video control.*/ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* video_control Pointer to video control */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_short_put Put 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_control_value_set(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_CONTROL *video_control) +{ + +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT status; +UCHAR * control_buffer; + + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_video_name, (VOID *) video) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, video, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &video -> ux_host_class_video_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the control buffer. */ + control_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, 2); + if (control_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return an error. */ + return(UX_MEMORY_INSUFFICIENT); + } + + /* Update the control buffer with the current control value. */ + _ux_utility_short_put(control_buffer, (USHORT) video_control -> ux_host_class_video_control_cur); + + /* Protect the control endpoint semaphore here. It will be unprotected in the + transfer request function. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_device -> ux_device_protection_semaphore, UX_WAIT_FOREVER); + + /* Check for status. */ + if (status != UX_SUCCESS) + + /* Something went wrong. */ + return(status); + + /* Create a transfer request for the GET_MIN request. */ + transfer_request -> ux_transfer_request_data_pointer = control_buffer; + transfer_request -> ux_transfer_request_requested_length = 2; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_VIDEO_SET_CUR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = (video_control -> ux_host_class_video_control << 8); + transfer_request -> ux_transfer_request_index = video -> ux_host_class_video_control_interface_number | (video -> ux_host_class_video_feature_unit_id << 8); + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer. */ + if (status != UX_SUCCESS) + { + + /* Free the previous control buffer. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(UX_TRANSFER_ERROR); + } + + /* Free all used resources. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_deactivate.c b/common/usbx_host_classes/src/ux_host_class_video_deactivate.c new file mode 100644 index 0000000..928a77e --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_deactivate.c @@ -0,0 +1,131 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called when this instance of the video has been */ +/* removed from the bus either directly or indirectly. The iso pipes */ +/* will be destroyed and the instanced removed. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_destroy Destroy class instance */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort outstanding transfer */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_thread_schedule_other Schedule other threads */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_deactivate(UX_HOST_CLASS_COMMAND *command) +{ + +UX_HOST_CLASS_VIDEO *video; +UINT status; + + /* Get the instance for this class. */ + video= (UX_HOST_CLASS_VIDEO *) command -> ux_host_class_command_instance; + + /* The video is being shut down. */ + video -> ux_host_class_video_state = UX_HOST_CLASS_INSTANCE_SHUTDOWN; + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + + /* Return error. */ + return(status); + + /* We need to abort transactions on the iso out pipe. */ + _ux_host_stack_endpoint_transfer_abort(video -> ux_host_class_video_isochronous_endpoint); + + /* The enumeration thread needs to sleep a while to allow the application or the class that may be using + endpoints to exit properly. */ + _ux_utility_thread_schedule_other(UX_THREAD_PRIORITY_ENUM); + + /* Destroy the instance. */ + _ux_host_stack_class_instance_destroy(video -> ux_host_class_video_class, (VOID *) video); + + /* Destroy the semaphore. */ + _ux_utility_semaphore_delete(&video -> ux_host_class_video_semaphore); + + /* Before we free the device resources, we need to inform the application + that the device is removed. */ + if (_ux_system_host -> ux_system_host_change_function != UX_NULL) + { + + /* Inform the application the device is removed. */ + _ux_system_host -> ux_system_host_change_function(UX_DEVICE_REMOVAL, video -> ux_host_class_video_class, (VOID *) video); + } + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_VIDEO_DEACTIVATE, video, 0, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* If trace is enabled, register this object. */ + //UX_TRACE_OBJECT_UNREGISTER(video); + + /* Free the video instance memory. */ + _ux_utility_memory_free(video); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_descriptor_get.c b/common/usbx_host_classes/src/ux_host_class_video_descriptor_get.c new file mode 100644 index 0000000..b2e68a0 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_descriptor_get.c @@ -0,0 +1,158 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_descriptor_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains the entire video configuration descriptors. */ +/* This is needed because the video class has many class specific */ +/* descriptors which describe the alternate settings that can be used. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_descriptor_get(UX_HOST_CLASS_VIDEO *video) +{ + +UCHAR * descriptor; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UX_CONFIGURATION configuration; +UINT status; +ULONG total_configuration_length; + + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &video -> ux_host_class_video_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Need to allocate memory for the descriptor. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_CONFIGURATION_DESCRIPTOR_LENGTH); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Create a transfer request for the GET_DESCRIPTOR request. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + transfer_request -> ux_transfer_request_requested_length = UX_CONFIGURATION_DESCRIPTOR_LENGTH; + transfer_request -> ux_transfer_request_function = UX_GET_DESCRIPTOR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_STANDARD | UX_REQUEST_TARGET_DEVICE; + transfer_request -> ux_transfer_request_value = UX_CONFIGURATION_DESCRIPTOR_ITEM << 8; + transfer_request -> ux_transfer_request_index = 0; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == UX_CONFIGURATION_DESCRIPTOR_LENGTH)) + { + + /* The descriptor is in a packed format, parse it locally. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_configuration_descriptor_structure, + UX_CONFIGURATION_DESCRIPTOR_ENTRIES, (UCHAR *) &configuration.ux_configuration_descriptor); + + /* Now we have the configuration descriptor which will tell us how many + bytes there are in the entire descriptor. */ + total_configuration_length = configuration.ux_configuration_descriptor.wTotalLength; + + /* Free the previous descriptor. */ + _ux_utility_memory_free(descriptor); + + /* Allocate enough memory to read all descriptors attached + to this configuration. We will save it until the class is unmounted. */ + descriptor = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, total_configuration_length); + if (descriptor == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Set the length we need to retrieve. */ + transfer_request -> ux_transfer_request_requested_length = total_configuration_length; + + /* And reprogram the descriptor buffer address. */ + transfer_request -> ux_transfer_request_data_pointer = descriptor; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer and entire descriptor returned. */ + if ((status == UX_SUCCESS) && (transfer_request -> ux_transfer_request_actual_length == total_configuration_length)) + { + + /* Save the address of the entire configuration descriptor of the video device. */ + video -> ux_host_class_video_configuration_descriptor = descriptor; + + /* Save the length of the entire descriptor too. */ + video -> ux_host_class_video_configuration_descriptor_length = total_configuration_length; + + /* We do not free the resource for the descriptor until the device is + plugged out. */ + return(UX_SUCCESS); + } + } + + /* Free all used resources. */ + _ux_utility_memory_free(descriptor); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_endpoints_get.c b/common/usbx_host_classes/src/ux_host_class_video_endpoints_get.c new file mode 100644 index 0000000..f67c2d2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_endpoints_get.c @@ -0,0 +1,119 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_endpoints_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function searches for the handle of the isochronous endpoints. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_interface_endpoint_get Get interface endpoint */ +/* _ux_system_error_handler Log system error */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_endpoints_get(UX_HOST_CLASS_VIDEO *video) +{ + +UINT status; +UINT endpoint_index; +UX_ENDPOINT *endpoint; + + + /* Search the ISO OUT endpoint. It is attached to the interface container. */ + for (endpoint_index = 0; endpoint_index < video -> ux_host_class_video_streaming_interface -> ux_interface_descriptor.bNumEndpoints; + endpoint_index++) + { + + /* Get interface endpoint. */ + status = _ux_host_stack_interface_endpoint_get(video -> ux_host_class_video_streaming_interface, endpoint_index, &endpoint); + + /* Check completion status. */ + if (status == UX_SUCCESS) + { + + /* Check if endpoint is iso and OUT. */ + if (((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == UX_ENDPOINT_OUT) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_ISOCHRONOUS_ENDPOINT)) + { + + /* We have found the bulk endpoint, save it. */ + video -> ux_host_class_video_isochronous_endpoint = endpoint; + break; + } + } + } + + /* The isochronous endpoint is mandatory. If we didn't find it, return an error. */ + if (video -> ux_host_class_video_isochronous_endpoint == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Return successful status. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_entry.c b/common/usbx_host_classes/src/ux_host_class_video_entry.c new file mode 100644 index 0000000..bc2049b --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_entry.c @@ -0,0 +1,129 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the entry point of the Video class. It will be */ +/* called by the USBX stack enumeration module when there is a new */ +/* video device (speaker, microphone ...) on the bus or when the video */ +/* device is removed. */ +/* */ +/* INPUT */ +/* */ +/* command Pointer to command */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_video_activate Activate video class */ +/* _ux_host_class_video_deactivate Deactivate video class */ +/* _ux_system_error_handler Log system error */ +/* */ +/* CALLED BY */ +/* */ +/* Host Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_entry(UX_HOST_CLASS_COMMAND *command) +{ + +UINT status = UX_SUCCESS; + + + /* The command request will tell us we need to do here, either a enumeration + query, an activation or a deactivation. */ + switch (command -> ux_host_class_command_request) + { + + + case UX_HOST_CLASS_COMMAND_QUERY: + + /* The query command is used to let the stack enumeration process know if we want to own + this device or not. */ + if ((command -> ux_host_class_command_usage == UX_HOST_CLASS_COMMAND_USAGE_CSP) && + (command -> ux_host_class_command_class == UX_HOST_CLASS_VIDEO_CLASS)) + status = UX_SUCCESS; + else + status = UX_NO_CLASS_MATCH; + break; + + case UX_HOST_CLASS_COMMAND_ACTIVATE: + + /* The activate command is used when the device inserted has found a parent and + is ready to complete the enumeration. */ + status = _ux_host_class_video_activate(command); + + break; + + + case UX_HOST_CLASS_COMMAND_DEACTIVATE: + + /* The deactivate command is used when the device has been extracted either + directly or when its parents has been extracted. */ + status = _ux_host_class_video_deactivate(command); + + break; + + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + status = UX_FUNCTION_NOT_SUPPORTED; + } + + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_format_data_get.c b/common/usbx_host_classes/src/ux_host_class_video_format_data_get.c new file mode 100644 index 0000000..9c86a1c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_format_data_get.c @@ -0,0 +1,176 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_format_data_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function finds the format data within the input terminal. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* format_parameter Format Parameter structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler Log system error */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_format_data_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_PARAMETER_FORMAT_DATA *format_parameter) +{ + +UCHAR *descriptor; +ULONG total_descriptor_length; +ULONG descriptor_length; +ULONG descriptor_type; +ULONG descriptor_subtype; + + + /* Get the descriptor to the selected format. */ + descriptor = video -> ux_host_class_video_format_address; + total_descriptor_length = video -> ux_host_class_video_length_formats; + + /* Descriptors are arranged in order. First FORMAT then FRAME. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Must be CS_INTERFACE. */ + if (descriptor_type == UX_HOST_CLASS_VIDEO_CS_INTERFACE) + { + + /* Process relative to descriptor type. */ + switch (descriptor_subtype) + { + + case UX_HOST_CLASS_VIDEO_VS_FORMAT_UNCOMPRESSED : + case UX_HOST_CLASS_VIDEO_VS_FORMAT_MJPEG : + case UX_HOST_CLASS_VIDEO_VS_FORMAT_MPEG2TS : + case UX_HOST_CLASS_VIDEO_VS_FORMAT_DV : + case UX_HOST_CLASS_VIDEO_VS_FORMAT_FRAME_BASED : + case UX_HOST_CLASS_VIDEO_VS_FORMAT_STREAM_BASED : + + + /* We found a Format descriptor. Is it the right one ? */ + if (format_parameter -> ux_host_class_video_parameter_format_requested == *(descriptor + 3)) + { + + /* Save the subtype for this format. */ + format_parameter -> ux_host_class_video_parameter_format_subtype = descriptor_subtype; + + /* Save the number of frame descriptors associated with this format. */ + format_parameter -> ux_host_class_video_parameter_number_frame_descriptors = *(descriptor + 4); + + /* Save the address of this format. */ + video -> ux_host_class_video_current_format_address = descriptor; + + /* And the current format index. */ + video -> ux_host_class_video_current_format = format_parameter -> ux_host_class_video_parameter_format_requested; + + /* We are done here. */ + return(UX_SUCCESS); + + } + + break; + + } + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_TYPE); + + /* We get here when either the report descriptor has a problem or we could + not find the right video device. */ + return(UX_HOST_CLASS_VIDEO_WRONG_TYPE); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_frame_data_get.c b/common/usbx_host_classes/src/ux_host_class_video_frame_data_get.c new file mode 100644 index 0000000..7abb99c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_frame_data_get.c @@ -0,0 +1,176 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_frame_data_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function finds the frame data within the input terminal. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* frame_data Frame request structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler Log system error */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_frame_data_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_DATA *frame_parameter) +{ + +UCHAR *descriptor; +UX_HOST_CLASS_VIDEO_FRAME_DESCRIPTOR frame_descriptor; +ULONG total_descriptor_length; +ULONG descriptor_length; +ULONG descriptor_type; +ULONG descriptor_subtype; + + + /* Get the descriptor to the selected format. */ + descriptor = video -> ux_host_class_video_current_format_address; + total_descriptor_length = video -> ux_host_class_video_length_formats; + + /* Descriptors are arranged in order. First FORMAT then FRAME. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Must be CS_INTERFACE. */ + if (descriptor_type == UX_HOST_CLASS_VIDEO_CS_INTERFACE) + { + + /* Process relative to descriptor type. */ + switch (descriptor_subtype) + { + + case UX_HOST_CLASS_VIDEO_VS_FRAME_UNCOMPRESSED : + case UX_HOST_CLASS_VIDEO_VS_FRAME_MJPEG : + case UX_HOST_CLASS_VIDEO_VS_FRAME_FRAME_BASED : + + /* We found a Frame descriptor. Is it the right one ? */ + if (frame_parameter -> ux_host_class_video_parameter_frame_requested == *(descriptor + 3)) + { + + /* Make the descriptor machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_video_frame_descriptor_structure, + UX_HOST_CLASS_VIDEO_FRAME_DESCRIPTOR_ENTRIES, (UCHAR *) &frame_descriptor); + + + /* Save the frame subtype. */ + frame_parameter -> ux_host_class_video_parameter_frame_subtype = descriptor_type; + + /* Save useful frame parameters. */ + frame_parameter -> ux_host_class_video_parameter_frame_width = frame_descriptor.wWidth; + frame_parameter -> ux_host_class_video_parameter_frame_height = frame_descriptor.wHeight; + frame_parameter -> ux_host_class_video_parameter_default_frame_interval = frame_descriptor.dwDefaultFrameInterval; + frame_parameter -> ux_host_class_video_parameter_frame_interval_type = frame_descriptor.bFrameIntervalType; + video -> ux_host_class_video_current_frame_address = descriptor; + video -> ux_host_class_video_current_frame_interval = frame_descriptor.dwDefaultFrameInterval; + /* We are done here. */ + return(UX_SUCCESS); + } + + break; + + } + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + // UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_TYPE); + + /* We get here when either the report descriptor has a problem or we could + not find the right video device. */ + return(UX_HOST_CLASS_VIDEO_WRONG_TYPE); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_frame_interval_get.c b/common/usbx_host_classes/src/ux_host_class_video_frame_interval_get.c new file mode 100644 index 0000000..22a801a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_frame_interval_get.c @@ -0,0 +1,199 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_frame_interval_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function finds the frame intervals within the frame. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* interval_parameter Interval request structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler Log system error */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_utility_long_get Get 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_frame_interval_get(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_INTERVAL *interval_parameter) +{ + +UCHAR *descriptor; +UX_HOST_CLASS_VIDEO_FRAME_DESCRIPTOR frame_descriptor; +ULONG total_descriptor_length; +ULONG descriptor_length; +ULONG descriptor_type; +ULONG descriptor_subtype; +ULONG intervals_to_copy; +ULONG i; + + /* Get the descriptor to the selected format. */ + descriptor = video -> ux_host_class_video_current_format_address; + total_descriptor_length = video -> ux_host_class_video_length_formats; + + /* Descriptors are arranged in order. First FORMAT then FRAME. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Must be CS_INTERFACE. */ + if (descriptor_type == UX_HOST_CLASS_VIDEO_CS_INTERFACE) + { + + /* Process relative to descriptor type. */ + switch (descriptor_subtype) + { + + case UX_HOST_CLASS_VIDEO_VS_FRAME_UNCOMPRESSED : + case UX_HOST_CLASS_VIDEO_VS_FRAME_MJPEG : + case UX_HOST_CLASS_VIDEO_VS_FRAME_FRAME_BASED : + + /* We found a Frame descriptor. Is it the right one ? */ + if (interval_parameter -> ux_host_class_video_parameter_frame_requested == *(descriptor + 3)) + { + + /* Make the descriptor machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_video_frame_descriptor_structure, + UX_HOST_CLASS_VIDEO_FRAME_DESCRIPTOR_ENTRIES, (UCHAR *) &frame_descriptor); + + /* Check the frame interval type. */ + if (frame_descriptor.bFrameIntervalType == 0) + { + + /* Frame type is continuous, copy Min, Max and Step. */ + intervals_to_copy = 3; + } + else + { + + /* Frame type is discrete, copy number of frame intervals. */ + intervals_to_copy = frame_descriptor.bFrameIntervalType; + } + + /* Check if we have enough space to copy. */ + if (intervals_to_copy * sizeof(ULONG) > interval_parameter -> ux_host_class_video_parameter_frame_interval_buffer_length) + { + intervals_to_copy = interval_parameter -> ux_host_class_video_parameter_frame_interval_buffer_length / sizeof(ULONG); + } + + /* Return bytes copied. */ + interval_parameter -> ux_host_class_video_parameter_frame_interval_buffer_length_written = intervals_to_copy * sizeof(ULONG); + + /* Loop to copy interval data. */ + for (i = 0; i < intervals_to_copy; i++) + { + + /* Copy intervals to user buffer. */ + interval_parameter -> ux_host_class_video_parameter_frame_interval_buffer[i] = + _ux_utility_long_get(descriptor + 26 + i * sizeof(ULONG)); + } + + /* We are done here. */ + return(UX_SUCCESS); + } + + break; + + } + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_TYPE); + + /* We get here when either the report descriptor has a problem or we could + not find the right video device. */ + return(UX_HOST_CLASS_VIDEO_WRONG_TYPE); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_frame_parameters_set.c b/common/usbx_host_classes/src/ux_host_class_video_frame_parameters_set.c new file mode 100644 index 0000000..a9a86b2 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_frame_parameters_set.c @@ -0,0 +1,290 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_frame_parameters_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the video parameters for the video device. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* frame_format Video format to use */ +/* width Video frame width */ +/* height Video frame height */ +/* frame_interval Video frame interval */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_video_format_data_get Get format data */ +/* _ux_host_class_video_frame_data_get Get frame data */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_utility_long_get Read 32-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_frame_parameters_set(UX_HOST_CLASS_VIDEO *video, ULONG frame_format, ULONG width, ULONG height, ULONG frame_interval) +{ + +UX_HOST_CLASS_VIDEO_PARAMETER_FORMAT_DATA format_parameter; +UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_DATA frame_parameter; +UX_HOST_CLASS_VIDEO_FRAME_DESCRIPTOR frame_descriptor; +ULONG format_index; +ULONG frame_index; +UINT status; +ULONG min_frame_interval; +ULONG max_frame_interval; +ULONG frame_interval_step; +ULONG i; +UX_ENDPOINT *control_endpoint; +UX_TRANSFER *transfer_request; +UINT streaming_interface; +UCHAR *control_buffer; +ULONG max_payload_size; + + + /* Find the requested frame format. */ + for (format_index = 1; format_index <= video -> ux_host_class_video_number_formats; format_index++) + { + + /* Get format data for current format index. */ + format_parameter.ux_host_class_video_parameter_format_requested = format_index; + status = _ux_host_class_video_format_data_get(video, &format_parameter); + if (status != UX_SUCCESS) + { + return(status); + } + + /* Check if the format type is the one requested. */ + if (format_parameter.ux_host_class_video_parameter_format_subtype == frame_format) + { + + /* Save number of frames in the video instance. */ + video -> ux_host_class_video_number_frames = format_parameter.ux_host_class_video_parameter_number_frame_descriptors; + + /* The format is found and break the loop. */ + break; + } + } + + /* Check if the requested format is found. */ + if (format_index > video -> ux_host_class_video_number_formats) + { + return(UX_HOST_CLASS_VIDEO_PARAMETER_ERROR); + } + + /* Find the requested frame resolution. */ + for (frame_index = 1; frame_index <= video -> ux_host_class_video_number_frames; frame_index++) + { + + /* Get frame data for current frame index. */ + frame_parameter.ux_host_class_video_parameter_frame_requested = frame_index; + status = _ux_host_class_video_frame_data_get(video, &frame_parameter); + if (status != UX_SUCCESS) + { + return(status); + } + + /* Check the frame resolution. */ + if (frame_parameter.ux_host_class_video_parameter_frame_width == width && + frame_parameter.ux_host_class_video_parameter_frame_height == height) + { + + /* Save the current frame index. */ + video -> ux_host_class_video_current_frame = frame_index; + + /* The requested resolution is found, break the loop. */ + break; + } + } + + /* Check if the requested resolution is found. */ + if (frame_index > video -> ux_host_class_video_number_frames) + { + return(UX_HOST_CLASS_VIDEO_PARAMETER_ERROR); + } + + /* Make the descriptor machine independent. */ + _ux_utility_descriptor_parse(video -> ux_host_class_video_current_frame_address, + _ux_system_class_video_frame_descriptor_structure, + UX_HOST_CLASS_VIDEO_FRAME_DESCRIPTOR_ENTRIES, (UCHAR *) &frame_descriptor); + + /* Initial status for frame interval checking. */ + status = UX_HOST_CLASS_VIDEO_PARAMETER_ERROR; + + /* Check the frame interval type. */ + if (frame_descriptor.bFrameIntervalType == 0) + { + + /* Frame interval type is continuous. */ + min_frame_interval = _ux_utility_long_get(video -> ux_host_class_video_current_frame_address + 26); + max_frame_interval = _ux_utility_long_get(video -> ux_host_class_video_current_frame_address + 30); + frame_interval_step = _ux_utility_long_get(video -> ux_host_class_video_current_frame_address + 34); + + /* Check if the frame interval is valid. */ + if (frame_interval >= min_frame_interval && frame_interval <= max_frame_interval && + ((frame_interval - min_frame_interval) % frame_interval_step == 0)) + { + + /* Save the frame interval. */ + video -> ux_host_class_video_current_frame_interval = frame_interval; + status = UX_SUCCESS; + } + } + else + { + + /* Frame interval type is discrete. */ + for(i = 0; i < frame_descriptor.bFrameIntervalType; i++) + { + + /* Check if the requested frame interval is valid. */ + if (frame_interval == _ux_utility_long_get(video -> ux_host_class_video_current_frame_address + 26 + i * sizeof(ULONG))) + { + + /* Save the frame interval. */ + video -> ux_host_class_video_current_frame_interval = frame_interval; + status = UX_SUCCESS; + } + } + } + + if (status != UX_SUCCESS) + return(UX_HOST_CLASS_VIDEO_PARAMETER_ERROR); + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + + /* We need to get the default control endpoint transfer request pointer. */ + control_endpoint = &video -> ux_host_class_video_device -> ux_device_control_endpoint; + transfer_request = &control_endpoint -> ux_endpoint_transfer_request; + + /* Get the interface number of the video streaming interface. */ + streaming_interface = video -> ux_host_class_video_streaming_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* Need to allocate memory for the control_buffer. */ + control_buffer = _ux_utility_memory_allocate(UX_SAFE_ALIGN, UX_CACHE_SAFE_MEMORY, UX_HOST_CLASS_VIDEO_PROBE_COMMIT_LENGTH); + if (control_buffer == UX_NULL) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return error. */ + return(UX_MEMORY_INSUFFICIENT); + } + + *(control_buffer + UX_HOST_CLASS_VIDEO_PROBE_COMMIT_FORMAT_INDEX) = (UCHAR)format_index; + *(control_buffer + UX_HOST_CLASS_VIDEO_PROBE_COMMIT_FRAME_INDEX) = (UCHAR)frame_index; + _ux_utility_long_put(control_buffer + UX_HOST_CLASS_VIDEO_PROBE_COMMIT_FRAME_INTERVAL, frame_interval); + + /* Create a transfer request for the SET_CUR buffer request. */ + transfer_request -> ux_transfer_request_data_pointer = control_buffer; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_VIDEO_PROBE_COMMIT_LENGTH; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_VIDEO_SET_CUR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_OUT | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_VIDEO_VS_PROBE_CONTROL << 8; + transfer_request -> ux_transfer_request_index = streaming_interface; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Check for correct transfer. Buffer may not be all what we asked for. */ + if (status == UX_SUCCESS) + { + + + /* Create a transfer request for the GET_CUR buffer request. */ + transfer_request -> ux_transfer_request_data_pointer = control_buffer; + transfer_request -> ux_transfer_request_requested_length = UX_HOST_CLASS_VIDEO_PROBE_COMMIT_LENGTH; + transfer_request -> ux_transfer_request_function = UX_HOST_CLASS_VIDEO_GET_CUR; + transfer_request -> ux_transfer_request_type = UX_REQUEST_IN | UX_REQUEST_TYPE_CLASS | UX_REQUEST_TARGET_INTERFACE; + transfer_request -> ux_transfer_request_value = UX_HOST_CLASS_VIDEO_VS_PROBE_CONTROL << 8; + transfer_request -> ux_transfer_request_index = streaming_interface; + + /* Send request to HCD layer. */ + status = _ux_host_stack_transfer_request(transfer_request); + + } + + /* Get the max payload transfer size returned from video device. */ + max_payload_size = _ux_utility_long_get(control_buffer + UX_HOST_CLASS_VIDEO_PROBE_COMMIT_MAX_PAYLOAD_TRANSFER_SIZE); + + /* Free all used resources. */ + _ux_utility_memory_free(control_buffer); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Check the transfer status. */ + if (status == UX_SUCCESS) + { + + /* Save the maximum payload size returned by the device. */ + video -> ux_host_class_video_current_max_payload_size = max_payload_size; + return(UX_SUCCESS); + } + else + { + + /* The probe process failed. Return error. */ + return(UX_HOST_CLASS_VIDEO_PARAMETER_ERROR); + } +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_input_format_get.c b/common/usbx_host_classes/src/ux_host_class_video_input_format_get.c new file mode 100644 index 0000000..e44338c --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_input_format_get.c @@ -0,0 +1,201 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_input_format_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function finds the input format(s) for the input terminal. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* _ux_system_error_handler Log system error */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_input_format_get(UX_HOST_CLASS_VIDEO *video) +{ + +UCHAR *descriptor; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UX_HOST_CLASS_VIDEO_INPUT_HEADER_DESCRIPTOR input_header_descriptor; +ULONG total_descriptor_length; +ULONG descriptor_length; +ULONG descriptor_type; +ULONG descriptor_subtype; +ULONG descriptor_found; + + + /* Get the descriptor to the entire configuration. */ + descriptor = video -> ux_host_class_video_configuration_descriptor; + total_descriptor_length = video -> ux_host_class_video_configuration_descriptor_length; + + /* Default is Interface descriptor not yet found. */ + descriptor_found = UX_FALSE; + + /* Scan the descriptor for the Video Streaming interface. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Process relative to the descriptor type. */ + switch (descriptor_type) + { + + + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &interface_descriptor); + + /* Ensure we have the correct interface for Video Streaming. */ + if ((interface_descriptor.bInterfaceClass == UX_HOST_CLASS_VIDEO_CLASS) && + (interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_VIDEO_SUBCLASS_STREAMING)) + { + + /* Mark we have found it. */ + descriptor_found = UX_TRUE; + } + else + { + + descriptor_found = UX_FALSE; + } + break; + + + case UX_HOST_CLASS_VIDEO_CS_INTERFACE: + + /* First make sure we have found the correct generic interface descriptor. */ + if (descriptor_found == UX_TRUE) + { + + /* Check the sub type. */ + switch (descriptor_subtype) + { + + + case UX_HOST_CLASS_VIDEO_VS_INPUT_HEADER: + + /* Make the descriptor machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_video_input_header_descriptor_structure, + UX_HOST_CLASS_VIDEO_INPUT_HEADER_DESCRIPTOR_ENTRIES, (UCHAR *) &input_header_descriptor); + + /* Get the number of formats. */ + video -> ux_host_class_video_number_formats = input_header_descriptor.bNumFormats; + + /* Get the length of formats. */ + video -> ux_host_class_video_length_formats = input_header_descriptor.wTotalLength; + + /* Save the descriptor where the formats reside. */ + video -> ux_host_class_video_format_address = descriptor; + + /* We are done here. */ + return(UX_SUCCESS); + + } + } + break; + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_TYPE); + + /* We get here when either the report descriptor has a problem or we could + not find the right video device. */ + return(UX_HOST_CLASS_VIDEO_WRONG_TYPE); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_input_terminal_get.c b/common/usbx_host_classes/src/ux_host_class_video_input_terminal_get.c new file mode 100644 index 0000000..426764a --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_input_terminal_get.c @@ -0,0 +1,195 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_input_terminal_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function finds the input terminal in the config descriptor. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_system_error_handler System error log */ +/* _ux_utility_descriptor_parse Parse descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_input_terminal_get(UX_HOST_CLASS_VIDEO *video) +{ + +UCHAR *descriptor; +UX_INTERFACE_DESCRIPTOR interface_descriptor; +UX_HOST_CLASS_VIDEO_INPUT_TERMINAL_DESCRIPTOR input_terminal_descriptor; +ULONG total_descriptor_length; +ULONG descriptor_length; +ULONG descriptor_type; +ULONG descriptor_subtype; +ULONG interface_found; + + + /* Get the descriptor to the selected format. */ + descriptor = video -> ux_host_class_video_configuration_descriptor; + total_descriptor_length = video -> ux_host_class_video_configuration_descriptor_length; + + /* Haven't found it yet. */ + interface_found = UX_FALSE; + + /* Scan the descriptor for the Video Streaming interface. */ + while (total_descriptor_length) + { + + /* Gather the length, type and subtype of the descriptor. */ + descriptor_length = *descriptor; + descriptor_type = *(descriptor + 1); + descriptor_subtype = *(descriptor + 2); + + /* Make sure this descriptor has at least the minimum length. */ + if (descriptor_length < 3) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Process relative to descriptor type. */ + switch (descriptor_type) + { + + case UX_INTERFACE_DESCRIPTOR_ITEM: + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_interface_descriptor_structure, + UX_INTERFACE_DESCRIPTOR_ENTRIES, (UCHAR *) &interface_descriptor); + + /* Ensure we have the correct interface for Video Control. */ + if ((interface_descriptor.bInterfaceClass == UX_HOST_CLASS_VIDEO_CLASS) && + (interface_descriptor.bInterfaceSubClass == UX_HOST_CLASS_VIDEO_SUBCLASS_CONTROL)) + { + + /* Mark we have found it. */ + interface_found = UX_TRUE; + + /* Get the interface number of this descriptor and save it in the video + instance. This will be useful to program the video controls. */ + video -> ux_host_class_video_control_interface_number = interface_descriptor.bInterfaceNumber; + } + else + { + + /* Haven't found it. */ + interface_found = UX_FALSE; + } + break; + + + case UX_HOST_CLASS_VIDEO_CS_INTERFACE: + + /* First make sure we have found the correct generic interface descriptor. */ + if ((interface_found == UX_TRUE) && (descriptor_subtype == UX_HOST_CLASS_VIDEO_VC_INPUT_TERMINAL)) + { + + /* Parse the interface descriptor and make it machine independent. */ + _ux_utility_descriptor_parse(descriptor, _ux_system_class_video_input_terminal_descriptor_structure, + UX_HOST_CLASS_VIDEO_INPUT_TERMINAL_DESCRIPTOR_ENTRIES, (UCHAR *) &input_terminal_descriptor); + + /* Save the video terminal ID. */ + video -> ux_host_class_video_terminal_id = input_terminal_descriptor.bTerminalID; + + /* Save the video terminal type. */ + video -> ux_host_class_video_terminal_type = input_terminal_descriptor.wTerminalType; + + + /* We are done here. */ + return(UX_SUCCESS); + } + + break; + } + + /* Verify if the descriptor is still valid. */ + if (descriptor_length > total_descriptor_length) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_DESCRIPTOR_CORRUPTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_DESCRIPTOR_CORRUPTED, descriptor, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_DESCRIPTOR_CORRUPTED); + } + + /* Jump to the next descriptor if we have not reached the end. */ + descriptor += descriptor_length; + + /* And adjust the length left to parse in the descriptor. */ + total_descriptor_length -= descriptor_length; + } + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_TYPE); + + /* We get here when either the report descriptor has a problem or we could + not find the right video device. */ + return(UX_HOST_CLASS_VIDEO_WRONG_TYPE); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_ioctl.c b/common/usbx_host_classes/src/ux_host_class_video_ioctl.c new file mode 100644 index 0000000..a3dbd7e --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_ioctl.c @@ -0,0 +1,216 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** VIDEO Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_cdc_acm_ioctl PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the ioctl entry point for the application to */ +/* configure the video class based device. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* ioctl_function Ioctl function */ +/* parameter Pointer to structure */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_video_format_data_get Get video format data. */ +/* _ux_host_class_video_frame_data_get Get video frame data */ +/* _ux_host_class_video_frame_interval_get */ +/* Get video frame internal data.*/ +/* _ux_host_class_video_channel_start Start the video. */ +/* _ux_host_class_video_stop Stop the video. */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort the transfer */ +/* _ux_system_error_handler Log system error */ +/* */ +/* CALLED BY */ +/* */ +/* Storage Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_ioctl(UX_HOST_CLASS_VIDEO *video, ULONG ioctl_function, + VOID *parameter) +{ + +UINT status; +UX_HOST_CLASS_VIDEO_PARAMETER_INPUT_TERMINAL *input_terminal; +UX_HOST_CLASS_VIDEO_PARAMETER_NUMBER_FORMATS *number_formats; +UX_HOST_CLASS_VIDEO_PARAMETER_FORMAT_DATA *format_parameter; +UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_DATA *frame_parameter; +UX_HOST_CLASS_VIDEO_PARAMETER_CHANNEL *channel_parameter; +UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_INTERVAL *interval_parameter; + + /* Ensure the instance is valid. */ + if ((video -> ux_host_class_video_state != UX_HOST_CLASS_INSTANCE_LIVE) && + (video -> ux_host_class_video_state != UX_HOST_CLASS_INSTANCE_MOUNTING)) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, video, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* The command request will tell us what we need to do here. */ + switch (ioctl_function) + { + + case UX_HOST_CLASS_VIDEO_IOCTL_GET_INPUT_TERMINAL: + + /* Set status to error by default. */ + status = UX_ERROR; + + /* Is the video terminal defined ? */ + if (video -> ux_host_class_video_terminal_id != 0) + { + + /* Cast answer. */ + input_terminal = (UX_HOST_CLASS_VIDEO_PARAMETER_INPUT_TERMINAL *) parameter; + + /* Return input terminal id. */ + input_terminal -> ux_host_class_video_parameter_input_terminal_id = video -> ux_host_class_video_terminal_id; + + /* Return input terminal type. */ + input_terminal -> ux_host_class_video_parameter_input_terminal_type = video -> ux_host_class_video_terminal_type; + + /* Status ok. */ + status = UX_SUCCESS; + } + + break; + + case UX_HOST_CLASS_VIDEO_IOCTL_GET_FORMAT_NUMBER: + + /* Cast answer. */ + number_formats = (UX_HOST_CLASS_VIDEO_PARAMETER_NUMBER_FORMATS *) parameter; + + /* Save the number of formats. */ + number_formats -> ux_host_class_video_parameter_number_formats = video -> ux_host_class_video_number_formats; + + /* Status ok. */ + status = UX_SUCCESS; + + break; + + case UX_HOST_CLASS_VIDEO_IOCTL_GET_FORMAT_DATA: + + /* Cast answer. */ + format_parameter = (UX_HOST_CLASS_VIDEO_PARAMETER_FORMAT_DATA *) parameter; + + /* Get the format data for the format index requested. */ + status = _ux_host_class_video_format_data_get(video, format_parameter); + break; + + case UX_HOST_CLASS_VIDEO_IOCTL_GET_FRAME_DATA: + + /* Cast answer. */ + frame_parameter = (UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_DATA *) parameter; + + /* Get the frame data for the frame index requested. */ + status = _ux_host_class_video_frame_data_get(video, frame_parameter); + break; + + case UX_HOST_CLASS_VIDEO_IOCTL_GET_FRAME_INTERVAL: + + /* Cast answer. */ + interval_parameter = (UX_HOST_CLASS_VIDEO_PARAMETER_FRAME_INTERVAL *) parameter; + + /* Get the frame intervals for the frame index requested. */ + status = _ux_host_class_video_frame_interval_get(video, interval_parameter); + break; + + case UX_HOST_CLASS_VIDEO_IOCTL_CHANNEL_START: + + /* Cast answer. */ + channel_parameter = (UX_HOST_CLASS_VIDEO_PARAMETER_CHANNEL *) parameter; + + /* Start the channel for reading video input. */ + status = _ux_host_class_video_channel_start(video, channel_parameter); + break; + + case UX_HOST_CLASS_VIDEO_IOCTL_CHANNEL_STOP: + + /* Stop the channel. */ + status = _ux_host_class_video_stop(video); + break; + + + case UX_HOST_CLASS_VIDEO_IOCTL_ABORT_IN_PIPE : + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_HOST_CLASS_VIDEO_IOCTL_ABORT_IN_PIPE, video, video -> ux_host_class_video_isochronous_endpoint, 0, 0, UX_TRACE_HOST_CLASS_EVENTS, 0, 0) + + /* We need to abort transactions on the bulk In pipe. */ + _ux_host_stack_endpoint_transfer_abort(video -> ux_host_class_video_isochronous_endpoint); + + /* Status is successful. */ + status = UX_SUCCESS; + break; + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + //UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Function not supported. Return an error. */ + status = UX_FUNCTION_NOT_SUPPORTED; + } + + /* Return status to caller. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_max_payload_get.c b/common/usbx_host_classes/src/ux_host_class_video_max_payload_get.c new file mode 100644 index 0000000..8402d8f --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_max_payload_get.c @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_max_payload_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the maximum transfer size in a single payload */ +/* transfer. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* */ +/* OUTPUT */ +/* */ +/* Maximum payload transfer size */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_host_class_video_max_payload_get(UX_HOST_CLASS_VIDEO *video) +{ + + /* Return the maximum payload size. */ + return(video ->ux_host_class_video_current_max_payload_size); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_read.c b/common/usbx_host_classes/src/ux_host_class_video_read.c new file mode 100644 index 0000000..1e92c98 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_read.c @@ -0,0 +1,151 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads from the video streaming interface. */ +/* */ +/* Note if the transfer request is not linked (next pointer is NULL), */ +/* a single request is performed. If the transfer request links into a */ +/* list, the whole list is added. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* video_transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_video_transfer_request Video transfer request */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_system_error_handler System error log */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_read(UX_HOST_CLASS_VIDEO *video, UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST *video_transfer_request) +{ + +UINT status; +ULONG packet_size; +UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST *transfer_list; + + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_video_name, (VOID *) video) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* By default the transmission will be successful. */ + status = UX_SUCCESS; + + /* Ensure we have a selected interface that allows isoch transmission. */ + if ((video -> ux_host_class_video_isochronous_endpoint == UX_NULL) || + (video -> ux_host_class_video_isochronous_endpoint -> ux_endpoint_descriptor.wMaxPacketSize == 0)) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_INTERFACE); + + /* Return error status. */ + return(UX_HOST_CLASS_VIDEO_WRONG_INTERFACE); + } + + /* Calculate max transfer size on the endpoint. */ + packet_size = video -> ux_host_class_video_isochronous_endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + if (packet_size & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK) + packet_size = (packet_size & UX_MAX_PACKET_SIZE_MASK) * (((packet_size & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK) >> UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT) + 1); + + /* Save list head. */ + transfer_list = video_transfer_request; + + /* Handle the request (list). */ + while(video_transfer_request) + { + + /* For video in, we read packets at a time, so the transfer request size is the size of the + endpoint. */ + video_transfer_request -> ux_host_class_video_transfer_request_requested_length = packet_size; + + /* Next request. */ + video_transfer_request = video_transfer_request -> ux_host_class_video_transfer_request_next_video_transfer_request; + + } + + /* Ask the stack to hook this transfer request to the iso ED. */ + status = _ux_host_class_video_transfer_request(video, transfer_list); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_start.c b/common/usbx_host_classes/src/ux_host_class_video_start.c new file mode 100644 index 0000000..f3396cc --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_start.c @@ -0,0 +1,93 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_start PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts the video streaming. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_class_video_channel_start Start video device */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_start(UX_HOST_CLASS_VIDEO *video) +{ + +UX_HOST_CLASS_VIDEO_PARAMETER_CHANNEL channel_parameter; +UINT status; + + + /* Get current parameters from the video instance. */ + channel_parameter.ux_host_class_video_parameter_format_requested = video -> ux_host_class_video_current_format; + channel_parameter.ux_host_class_video_parameter_frame_requested = video -> ux_host_class_video_current_frame; + channel_parameter.ux_host_class_video_parameter_frame_interval_requested = video -> ux_host_class_video_current_frame_interval; + channel_parameter.ux_host_class_video_parameter_channel_bandwidth_selection = 0; + + /* Start the video with the parameters. */ + status = _ux_host_class_video_channel_start(video, &channel_parameter); + + /* Reset indices for transfer requests. */ + video -> ux_host_class_video_transfer_request_start_index = 0; + video -> ux_host_class_video_transfer_request_end_index = 0; + + /* Return status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_stop.c b/common/usbx_host_classes/src/ux_host_class_video_stop.c new file mode 100644 index 0000000..6789430 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_stop.c @@ -0,0 +1,144 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_stop PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function stops the video channel. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_endpoint_transfer_abort */ +/* Abort outstanding transfer */ +/* _ux_host_stack_interface_setting_select */ +/* Select interface */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_stop(UX_HOST_CLASS_VIDEO *video) +{ + +UINT status; +UX_CONFIGURATION *configuration; +UX_INTERFACE *interface; +UINT streaming_interface; + + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + + /* Get the interface number of the video streaming interface. */ + streaming_interface = video -> ux_host_class_video_streaming_interface -> ux_interface_descriptor.bInterfaceNumber; + + /* We need to abort transactions on the iso pipe. */ + if (video -> ux_host_class_video_isochronous_endpoint != UX_NULL) + { + + /* Abort the iso transfer. */ + _ux_host_stack_endpoint_transfer_abort(video -> ux_host_class_video_isochronous_endpoint); + } + + /* We found the alternate setting for the sampling values demanded, now we need + to search its container. */ + configuration = video -> ux_host_class_video_streaming_interface -> ux_interface_configuration; + interface = configuration -> ux_configuration_first_interface; + + /* Scan all interfaces. */ + while (interface != UX_NULL) + { + + /* We search for both the right interface and alternate setting. */ + if ((interface -> ux_interface_descriptor.bInterfaceNumber == streaming_interface) && + (interface -> ux_interface_descriptor.bAlternateSetting == 0)) + { + + /* We have found the right interface/alternate setting combination + The stack will select it for us. */ + status = _ux_host_stack_interface_setting_select(interface); + + /* If the alternate setting for the streaming interface could be selected, we memorize it. */ + if (status == UX_SUCCESS) + { + + /* Memorize the interface. */ + video -> ux_host_class_video_streaming_interface = interface; + + /* There is no endpoint for the alternate setting 0. */ + video -> ux_host_class_video_isochronous_endpoint = UX_NULL; + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return successful completion. */ + return(UX_SUCCESS); + } + } + + /* Move to next interface. */ + interface = interface -> ux_interface_next_interface; + } + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_transfer_buffer_add.c b/common/usbx_host_classes/src/ux_host_class_video_transfer_buffer_add.c new file mode 100644 index 0000000..d7f6daa --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_transfer_buffer_add.c @@ -0,0 +1,161 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_transfer_buffer_add PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds a buffer for video transfer requests. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* buffer Pointer to data buffer */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_system_error_handler Log system error */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_transfer_buffer_add(UX_HOST_CLASS_VIDEO *video, UCHAR* buffer) +{ + +UINT status; +UX_TRANSFER *transfer_request; +ULONG transfer_index; +ULONG packet_size; + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_video_name, (VOID *) video) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + // UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_HOST_CLASS_INSTANCE_UNKNOWN, video, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* Ensure we have a selected interface that allows isoch transmission. */ + if ((video -> ux_host_class_video_isochronous_endpoint == UX_NULL) || + (video -> ux_host_class_video_isochronous_endpoint -> ux_endpoint_descriptor.wMaxPacketSize == 0)) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_INTERFACE); + + /* Return error status. */ + return(UX_HOST_CLASS_VIDEO_WRONG_INTERFACE); + } + + transfer_index = video->ux_host_class_video_transfer_request_start_index; + transfer_index ++; + if (transfer_index == UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_COUNT) + transfer_index = 0; + if (transfer_index == video->ux_host_class_video_transfer_request_end_index) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return error status. */ + return(UX_MEMORY_ARRAY_FULL); + } + + transfer_request = &video->ux_host_class_video_transfer_requests[video->ux_host_class_video_transfer_request_start_index]; + video->ux_host_class_video_transfer_request_start_index = transfer_index; + + /* Select the direction. We do this by taking the endpoint direction. */ + transfer_request -> ux_transfer_request_type = video -> ux_host_class_video_isochronous_endpoint -> + ux_endpoint_descriptor.bEndpointAddress & UX_REQUEST_DIRECTION; + + /* Calculate packet size. */ + packet_size = video -> ux_host_class_video_isochronous_endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + if (packet_size & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK) + packet_size = (packet_size & UX_MAX_PACKET_SIZE_MASK) * (((packet_size & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK) >> UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT) + 1); + + /* Fill the transfer request with all the required fields. */ + transfer_request -> ux_transfer_request_endpoint = video -> ux_host_class_video_isochronous_endpoint; + transfer_request -> ux_transfer_request_data_pointer = buffer; + transfer_request -> ux_transfer_request_requested_length = packet_size; + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_video_transfer_request_callback; + transfer_request -> ux_transfer_request_class_instance = video; + + /* Add single transfer. */ + transfer_request -> ux_transfer_request_next_transfer_request = UX_NULL; + + /* Transfer the transfer request. */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_transfer_buffers_add.c b/common/usbx_host_classes/src/ux_host_class_video_transfer_buffers_add.c new file mode 100644 index 0000000..1d36642 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_transfer_buffers_add.c @@ -0,0 +1,208 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_transfer_buffers_add PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds buffers for video transfer requests. */ +/* */ +/* Usually it's the very first step to start a video stream on a high */ +/* bandwidth isochronous endpoint. Since adding new buffer while */ +/* the prepared buffers in progress helps to improve performance. */ +/* */ +/* Note the maximum number of transfers could be buffered is */ +/* UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_COUNT - 1. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* buffers Pointer to data buffer */ +/* pointers array */ +/* num_buffers Number of data buffers */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_class_instance_verify Verify instance is valid */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* _ux_system_error_handler Log system error */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_transfer_buffers_add(UX_HOST_CLASS_VIDEO *video, UCHAR** buffers, ULONG num_buffers) +{ + +UINT status; +UX_TRANSFER *transfer_request; +UX_TRANSFER *previous_transfer; +ULONG transfer_index; +ULONG packet_size; +UINT i; + + + /* Ensure the instance is valid. */ + if (_ux_host_stack_class_instance_verify(_ux_system_host_class_video_name, (VOID *) video) != UX_SUCCESS) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_INSTANCE_UNKNOWN); + + return(UX_HOST_CLASS_INSTANCE_UNKNOWN); + } + + /* Protect thread reentry to this instance. */ + status = _ux_utility_semaphore_get(&video -> ux_host_class_video_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return(status); + + /* Ensure we have a selected interface that allows isoch transmission. */ + if ((video -> ux_host_class_video_isochronous_endpoint == UX_NULL) || + (video -> ux_host_class_video_isochronous_endpoint -> ux_endpoint_descriptor.wMaxPacketSize == 0)) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_HOST_CLASS_VIDEO_WRONG_INTERFACE); + + /* Return error status. */ + return(UX_HOST_CLASS_VIDEO_WRONG_INTERFACE); + } + + /* Check if there is enough requests available. */ + if (video -> ux_host_class_video_transfer_request_start_index >= + video -> ux_host_class_video_transfer_request_end_index) + { + + if (video -> ux_host_class_video_transfer_request_start_index + num_buffers >= + video -> ux_host_class_video_transfer_request_end_index + UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_COUNT) + status = (UX_MEMORY_ARRAY_FULL); + } + else + { + if (video -> ux_host_class_video_transfer_request_start_index + num_buffers >= + video -> ux_host_class_video_transfer_request_end_index) + status = (UX_MEMORY_ARRAY_FULL); + } + + /* Check error. */ + if (status != UX_SUCCESS) + { + + /* Unprotect thread reentry to this instance. */ + status = _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return error status. */ + return(status); + } + + /* Calculate packet size. */ + packet_size = video -> ux_host_class_video_isochronous_endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + if (packet_size & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK) + packet_size = (packet_size & UX_MAX_PACKET_SIZE_MASK) * (((packet_size & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK) >> UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT) + 1); + + /* Add buffers one by one. */ + for (i = 0, + transfer_index = video -> ux_host_class_video_transfer_request_start_index, + previous_transfer = UX_NULL; + i < num_buffers; i ++) + { + + transfer_request = &video->ux_host_class_video_transfer_requests[transfer_index]; + + /* Select the direction. We do this by taking the endpoint direction. */ + transfer_request -> ux_transfer_request_type = video -> ux_host_class_video_isochronous_endpoint -> + ux_endpoint_descriptor.bEndpointAddress & UX_REQUEST_DIRECTION; + + /* Fill the transfer request with all the required fields. */ + transfer_request -> ux_transfer_request_endpoint = video -> ux_host_class_video_isochronous_endpoint; + transfer_request -> ux_transfer_request_data_pointer = buffers[i]; + transfer_request -> ux_transfer_request_requested_length = packet_size; + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_video_transfer_request_callback; + transfer_request -> ux_transfer_request_class_instance = video; + + /* Confirm the transfer request is single one. */ + transfer_request -> ux_transfer_request_next_transfer_request = UX_NULL; + + /* Link to transfer request tail. */ + if (previous_transfer) + previous_transfer -> ux_transfer_request_next_transfer_request = transfer_request; + + /* Save as previous request. */ + previous_transfer = transfer_request; + + /* Move to next transfer request. */ + transfer_index ++; + if (transfer_index >= UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_COUNT) + transfer_index = 0; + } + + /* Get request list head. */ + transfer_request = &video -> ux_host_class_video_transfer_requests[video->ux_host_class_video_transfer_request_start_index]; + + /* Move request index. */ + video->ux_host_class_video_transfer_request_start_index = transfer_index; + + /* Transfer the transfer request (list). */ + status = _ux_host_stack_transfer_request(transfer_request); + + /* Unprotect thread reentry to this instance. */ + _ux_utility_semaphore_put(&video -> ux_host_class_video_semaphore); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_transfer_callback_set.c b/common/usbx_host_classes/src/ux_host_class_video_transfer_callback_set.c new file mode 100644 index 0000000..5702cff --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_transfer_callback_set.c @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_transfer_callback_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the callback function for video transfers. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* callback_function Pointer to callback function */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_video_transfer_callback_set(UX_HOST_CLASS_VIDEO *video, VOID (*callback_function)(UX_TRANSFER*)) +{ + + /* Save the callback function in the video instance. */ + video -> ux_host_class_video_transfer_completion_function = callback_function; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_transfer_request.c b/common/usbx_host_classes/src/ux_host_class_video_transfer_request.c new file mode 100644 index 0000000..fc2f989 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_transfer_request.c @@ -0,0 +1,130 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_transfer_request PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function submits an isochronous video transfer request or */ +/* isochronous video transfer request list to the USBX stack. */ +/* */ +/* Note if the transfer request is not linked (next pointer is NULL), */ +/* a single request is submitted. If the transfer request links into a */ +/* list, the whole list is submitted. */ +/* */ +/* INPUT */ +/* */ +/* video Pointer to video class */ +/* video_transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_host_stack_transfer_request Process transfer request */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_host_class_video_transfer_request(UX_HOST_CLASS_VIDEO *video, + UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST *video_transfer_request) +{ + +UINT status; +UX_TRANSFER *transfer_list; +UX_TRANSFER *transfer_request; +UX_TRANSFER *previous_transfer; + + /* Get transfer request list head. */ + transfer_list = &video_transfer_request -> ux_host_class_video_transfer_request; + + /* Process the transfer request list (if multiple found). */ + previous_transfer = UX_NULL; + while(video_transfer_request) + { + + /* The transfer request is embedded in the application transfer request. */ + transfer_request = &video_transfer_request -> ux_host_class_video_transfer_request; + + /* Select the direction. We do this by taking the endpoint direction. */ + transfer_request -> ux_transfer_request_type = video -> ux_host_class_video_isochronous_endpoint -> + ux_endpoint_descriptor.bEndpointAddress & UX_REQUEST_DIRECTION; + + /* Fill the transfer request with all the required fields. */ + transfer_request -> ux_transfer_request_endpoint = video -> ux_host_class_video_isochronous_endpoint; + transfer_request -> ux_transfer_request_data_pointer = video_transfer_request -> ux_host_class_video_transfer_request_data_pointer; + transfer_request -> ux_transfer_request_requested_length = video_transfer_request -> ux_host_class_video_transfer_request_requested_length; + transfer_request -> ux_transfer_request_completion_function = _ux_host_class_video_transfer_request_completed; + transfer_request -> ux_transfer_request_class_instance = video; + + /* We memorize the application transfer request in the local transfer request. */ + transfer_request -> ux_transfer_request_user_specific = (VOID *) video_transfer_request; + + /* Confirm transfer is not linking to others */ + transfer_request -> ux_transfer_request_next_transfer_request = UX_NULL; + + /* Add it to transfer list tail. */ + if (previous_transfer != UX_NULL) + previous_transfer -> ux_transfer_request_next_transfer_request = transfer_request; + + /* Save as previous transfer. */ + previous_transfer = transfer_request; + + /* Check next transfer request. */ + video_transfer_request = video_transfer_request -> ux_host_class_video_transfer_request_next_video_transfer_request; + } + + /* Transfer the transfer request (list). */ + status = _ux_host_stack_transfer_request(transfer_list); + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_transfer_request_callback.c b/common/usbx_host_classes/src/ux_host_class_video_transfer_request_callback.c new file mode 100644 index 0000000..620ea34 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_transfer_request_callback.c @@ -0,0 +1,102 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_transfer_request_callback PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives a completion call back on an isoch transfer */ +/* request. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_video_transfer_completion_function) */ +/* Transfer request completion */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_video_transfer_request_callback(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_VIDEO *video; +ULONG transfer_index; + + + /* Get the pointer to the video instance. */ + video = (UX_HOST_CLASS_VIDEO *) transfer_request -> ux_transfer_request_class_instance; + + /* Do a sanity check on the transfer request, if NULL something is wrong. */ + if (video == UX_NULL) + return; + + /* The caller's transfer request needs to be updated. */ + transfer_index = video -> ux_host_class_video_transfer_request_end_index; + transfer_index++; + if (transfer_index == UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST_COUNT) + transfer_index = 0; + + /* Update the transfer index. */ + video -> ux_host_class_video_transfer_request_end_index = transfer_index; + + /* Call the completion routine. */ + if (video -> ux_host_class_video_transfer_completion_function) + video -> ux_host_class_video_transfer_completion_function(transfer_request); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_classes/src/ux_host_class_video_transfer_request_completed.c b/common/usbx_host_classes/src/ux_host_class_video_transfer_request_completed.c new file mode 100644 index 0000000..088eb58 --- /dev/null +++ b/common/usbx_host_classes/src/ux_host_class_video_transfer_request_completed.c @@ -0,0 +1,96 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Video Class */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_class_video.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_host_class_video_transfer_request_completed PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives a completion call back on an isoch transfer */ +/* request. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* (ux_host_class_video_transfer_request_completion_function) */ +/* Transfer request completion */ +/* */ +/* CALLED BY */ +/* */ +/* Video Class */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_host_class_video_transfer_request_completed(UX_TRANSFER *transfer_request) +{ + +UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST *video_transfer_request; + + + /* Get the pointer to the video specific transfer request, by nature of the lined transfer requests, + the corresponding transfer request has to be the head transfer request in the video instance. */ + video_transfer_request = (UX_HOST_CLASS_VIDEO_TRANSFER_REQUEST *) transfer_request -> ux_transfer_request_user_specific; + + /* Do a sanity check on the transfer request, if NULL something is wrong. */ + if (video_transfer_request == UX_NULL) + return; + + /* The caller's transfer request needs to be updated. */ + video_transfer_request -> ux_host_class_video_transfer_request_actual_length = transfer_request -> ux_transfer_request_actual_length; + video_transfer_request -> ux_host_class_video_transfer_request_completion_code = transfer_request -> ux_transfer_request_completion_code; + + /* Call the completion routine. */ + video_transfer_request -> ux_host_class_video_transfer_request_completion_function(video_transfer_request); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_controllers/CMakeLists.txt b/common/usbx_host_controllers/CMakeLists.txt new file mode 100644 index 0000000..cdd0f20 --- /dev/null +++ b/common/usbx_host_controllers/CMakeLists.txt @@ -0,0 +1,93 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_asynch_td_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_done_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_door_bell_wait.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_ed_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_fsisochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_fsisochronous_tds_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_hsisochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_hsisochronous_tds_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_interrupt_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_isochronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_next_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_periodic_descriptor_link.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_poll_rate_entry_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_power_root_hubs.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_interrupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_request_transfer_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ehci_transfer_request_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_asynchronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_asynchronous_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_controller_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_done_queue_process.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_ed_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_endpoint_error_clear.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_endpoint_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_entry.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_frame_number_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_frame_number_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_interrupt_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_interrupt_handler.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_isochronous_endpoint_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_isochronous_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_least_traffic_list_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_next_td_clean.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_periodic_endpoint_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_periodic_tree_create.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_reset.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_resume.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_status_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_port_suspend.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_power_down_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_power_on_port.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_power_root_hubs.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_register_read.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_register_write.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_regular_td_obtain.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_request_bulk_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_request_control_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_request_interupt_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_request_isochronous_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_request_transfer.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_transfer_abort.c + ${CMAKE_CURRENT_LIST_DIR}/src/ux_hcd_ohci_transfer_request_process.c + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/common/usbx_host_controllers/inc/ux_hcd_ehci.h b/common/usbx_host_controllers/inc/ux_hcd_ehci.h new file mode 100644 index 0000000..d4a4c49 --- /dev/null +++ b/common/usbx_host_controllers/inc/ux_hcd_ehci.h @@ -0,0 +1,822 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_hcd_ehci.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX host EHCI Controller. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HCD_EHCI_H +#define UX_HCD_EHCI_H + + +/* Possible defined EHCI HCD extentions. */ + +/* Extension for peripheral host mode select (function like). */ +/* #define UX_HCD_EHCI_EXT_USB_HOST_MODE_ENABLE(hcd_ehci) */ + +/* Extension for embedded TT (UX_TRUE/UX_FALSE). */ +/* #define UX_HCD_EHCI_EXT_EMBEDDED_TT_SUPPORT */ + +/* Extension for phy high speed mode select (function like). */ +/* #define UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET(hcd_ehci, on_off) */ + +/* Define EHCI generic definitions. */ + +#define UX_EHCI_CONTROLLER 2 +#define UX_EHCI_MAX_PAYLOAD 16384 +#define UX_EHCI_FRAME_DELAY 4 +#define UX_EHCI_PAGE_SIZE 4096 +#define UX_EHCI_PAGE_ALIGN 0xfffff000 + + +/* Define EHCI host controller capability registers. */ + +#define EHCI_HCCR_CAP_LENGTH 0x00 +#define EHCI_HCCR_HCS_PARAMS 0x01 +#define EHCI_HCCR_HCC_PARAMS 0x02 +#define EHCI_HCCR_HCSP_PORT_ROUTE 0x03 + + +/* Define EHCI host controller registers. */ + +#define EHCI_HCOR_USB_COMMAND (hcd_ehci -> ux_hcd_ehci_hcor + 0x00) +#define EHCI_HCOR_USB_STATUS (hcd_ehci -> ux_hcd_ehci_hcor + 0x01) +#define EHCI_HCOR_USB_INTERRUPT (hcd_ehci -> ux_hcd_ehci_hcor + 0x02) +#define EHCI_HCOR_FRAME_INDEX (hcd_ehci -> ux_hcd_ehci_hcor + 0x03) +#define EHCI_HCOR_FRAME_LIST_BASE_ADDRESS (hcd_ehci -> ux_hcd_ehci_hcor + 0x05) +#define EHCI_HCOR_ASYNCH_LIST_ADDRESS (hcd_ehci -> ux_hcd_ehci_hcor + 0x06) +#define EHCI_HCOR_CONFIG_FLAG (hcd_ehci -> ux_hcd_ehci_hcor + 0x10) +#define EHCI_HCOR_PORT_SC (hcd_ehci -> ux_hcd_ehci_hcor + 0x11) + + +/* Define EHCI IO control register values. */ + +#define EHCI_HC_IO_RS 0x00000001 +#define EHCI_HC_IO_HCRESET 0x00000002 +#define EHCI_HC_IO_PSE 0x00000010 +#define EHCI_HC_IO_ASE 0x00000020 +#define EHCI_HC_IO_IAAD 0x00000040 +#define EHCI_HC_IO_ITC 0x00010000 +#define EHCI_HC_IO_FRAME_SIZE_1024 0x00000000 +#define EHCI_HC_IO_FRAME_SIZE_512 0x00000004 +#define EHCI_HC_IO_FRAME_SIZE_256 0x00000008 +#define EHCI_HC_IO_FRAME_SIZE_128 0x0000000C +#define EHCI_HC_IO_FRAME_SIZE_64 0x00008000 +#define EHCI_HC_IO_FRAME_SIZE_32 0x00008004 + +/* The number if entries in the periodic tree can be changed to save space IF and only IF the PFLF flag in the HCCPARAMS register + allows it. Setting values less than 1024 in controllers without the ability to change the Frame List Size leads to a EHCI crash. */ + +#ifndef UX_EHCI_FRAME_LIST_ENTRIES +#define UX_EHCI_FRAME_LIST_ENTRIES 1024 +#endif +#define UX_EHCI_FRAME_LIST_MASK EHCI_HC_IO_FRAME_SIZE_1024 + +/* Define EHCI HCOR status register. */ + +#define EHCI_HC_STS_USB_INT 0x00000001 +#define EHCI_HC_STS_USB_ERR_INT 0x00000002 +#define EHCI_HC_STS_PCD 0x00000004 +#define EHCI_HC_STS_FLR 0x00000008 +#define EHCI_HC_STS_HSE 0x00000010 +#define EHCI_HC_STS_IAA 0x00000020 +#define EHCI_HC_STS_HC_HALTED 0x00001000 +#define EHCI_HC_STS_RECLAMATION 0x00002000 +#define EHCI_HC_STS_PSS 0x00004000 +#define EHCI_HC_STS_ASS 0x00008000 + +#define EHCI_HC_INTERRUPT_ENABLE_NORMAL (EHCI_HC_STS_USB_INT|EHCI_HC_STS_USB_ERR_INT|EHCI_HC_STS_PCD|EHCI_HC_STS_HSE|EHCI_HC_STS_IAA) + + +/* Define EHCI HCOR root HUB command/status. */ + +#define EHCI_HC_RH_PPC 0x00000010 +#define EHCI_HC_RH_PSM 0x00000100 +#define EHCI_HC_RH_NPS 0x00000200 +#define EHCI_HC_RH_DT 0x00000400 +#define EHCI_HC_RH_OCPM 0x00000800 +#define EHCI_HC_RH_NOCP 0x00001000 + +#define EHCI_HC_PS_CCS 0x00000001 +#define EHCI_HC_PS_CSC 0x00000002 +#define EHCI_HC_PS_PE 0x00000004 +#define EHCI_HC_PS_PEC 0x00000008 +#define EHCI_HC_PS_OCA 0x00000010 +#define EHCI_HC_PS_OCC 0x00000020 +#define EHCI_HC_PS_FPR 0x00000040 +#define EHCI_HC_PS_SUSPEND 0x00000080 +#define EHCI_HC_PS_PR 0x00000100 +#define EHCI_HC_PS_PP 0x00001000 +#define EHCI_HC_PS_SPEED_MASK 0x00000c00 +#define EHCI_HC_PS_SPEED_LOW 0x00000400 +#define EHCI_HC_PS_PO 0x00002000 +#define EHCI_HC_PS_EMBEDDED_TT_SPEED_MASK 0x0c000000 +#define EHCI_HC_PS_EMBEDDED_TT_SPEED_FULL 0x00000000 +#define EHCI_HC_PS_EMBEDDED_TT_SPEED_LOW 0x04000000 +#define EHCI_HC_PS_EMBEDDED_TT_SPEED_HIGH 0x08000000 + +#define EHCI_HC_RH_POWER_STABLE_DELAY 25 +#define EHCI_HC_RH_RESET_DELAY 50 +#define EHCI_HC_RH_RESET_SETTLE_DELAY 5 + + +/* Define EHCI interrupt status register definitions. */ + +#define EHCI_HC_INT_IE 0x00000001 +#define EHCI_HC_INT_EIE 0x00000002 +#define EHCI_HC_INT_PCIE 0x00000004 +#define EHCI_HC_INT_FLRE 0x00000008 +#define EHCI_HC_INT_HSER 0x00000010 +#define EHCI_HC_INT_IAAE 0x00000020 + + +/* Define EHCI frame interval definition. */ + +#define EHCI_HC_FM_INTERVAL_CLEAR 0x8000ffff +#define EHCI_HC_FM_INTERVAL_SET 0x27780000 + + +/* Define EHCI static definition. */ + +#define UX_EHCI_AVAILABLE_BANDWIDTH 6000 +#define UX_EHCI_STOP 0 +#define UX_EHCI_START 1 +#define UX_EHCI_ROUTE_TO_LOCAL_HC 1 +#define UX_EHCI_INIT_DELAY 1000 +#define UX_EHCI_RESET_RETRY 1000 +#define UX_EHCI_RESET_DELAY 100 +#define UX_EHCI_PORT_RESET_RETRY 10 +#define UX_EHCI_PORT_RESET_DELAY 50 + + +/* Define EHCI initialization values. */ + +#define UX_EHCI_COMMAND_STATUS_RESET 0 +#define UX_EHCI_INIT_RESET_DELAY 10 + + +/* Define EHCI completion code errors. */ + +#define UX_EHCI_NO_ERROR 0x00 +#define UX_EHCI_ERROR_CRC 0x01 +#define UX_EHCI_ERROR_BIT_STUFFING 0x02 +#define UX_EHCI_ERROR_DATA_TOGGLE 0x03 +#define UX_EHCI_ERROR_STALL 0x04 +#define UX_EHCI_ERROR_DEVICE_NOT_RESPONDING 0x05 +#define UX_EHCI_ERROR_PID_FAILURE 0x06 +#define UX_EHCI_ERROR_DATA_OVERRUN 0x08 +#define UX_EHCI_ERROR_DATA_UNDERRUN 0x09 +#define UX_EHCI_ERROR_BUFFER_OVERRUN 0x0c +#define UX_EHCI_ERROR_BUFFER_UNDERRUN 0x0d +#define UX_EHCI_ERROR_NOT_ACCESSED 0x0f +#define UX_EHCI_ERROR_NAK 0x10 +#define UX_EHCI_ERROR_BABBLE 0x11 + +/* EHCI general descriptor type (Link Pointer). */ + +#define UX_EHCI_LP_MASK (0xFFFFFFE0u) /* 32-byte align. */ + +#define UX_EHCI_TYP_MASK (0x3u<<1) +#define UX_EHCI_TYP_ITD (0x0u<<1) +#define UX_EHCI_TYP_QH (0x1u<<1) +#define UX_EHCI_TYP_SITD (0x2u<<1) +#define UX_EHCI_TYP_FSTN (0x3u<<1) + +#define UX_EHCI_T (0x1u<<0) + +/* EHCI general descriptor type (Capabilities). */ + +#define UX_EHCI_ENDPT_MASK (0xFu<<8) +#define UX_EHCI_ENDPT_SHIFT (8) + +#define UX_EHCI_DEVICE_ADDRESS_MASK (0x3Fu<<0) + +#define UX_EHCI_CMASK_MASK (0xFFu<<8) +#define UX_EHCI_CMASK_0 (0x01u<<8) +#define UX_EHCI_CMASK_1 (0x02u<<8) +#define UX_EHCI_CMASK_2 (0x04u<<8) +#define UX_EHCI_CMASK_3 (0x08u<<8) +#define UX_EHCI_CMASK_4 (0x10u<<8) +#define UX_EHCI_CMASK_5 (0x20u<<8) +#define UX_EHCI_CMASK_6 (0x40u<<8) +#define UX_EHCI_CMASK_7 (0x80u<<8) +#define UX_EHCI_CMASK_ISOOUT_ANY (0x00u<<8) +#define UX_EHCI_CMASK_INT_Y0 (0x1Cu<<8) +#define UX_EHCI_CMASK_INT_Y1 (0x31u<<8) +#define UX_EHCI_CMASK_INT_Y2 (0x70u<<8) +#define UX_EHCI_CMASK_INT_Y3 (0xE0u<<8) +#define UX_EHCI_CMASK_INT_Y4 (0xC1u<<8) +#define UX_EHCI_CMASK_INT_Y5 (0x81u<<8) +#define UX_EHCI_CMASK_INT_Y7 (0x07u<<8) +#define UX_EHCI_CMASK_ISOIN_C1 (0x01u<<8) +#define UX_EHCI_CMASK_ISOIN_C2 (0x03u<<8) +#define UX_EHCI_CMASK_ISOIN_C3 (0x07u<<8) +#define UX_EHCI_CMASK_ISOIN_C4 (0x0Fu<<8) +#define UX_EHCI_CMASK_ISOIN_C5 (0x1Fu<<8) +#define UX_EHCI_CMASK_ISOIN_C6 (0x3Fu<<8) + +#define UX_EHCI_SMASK_MASK (0xFFu<<0) +#define UX_EHCI_SMASK_0 (0x01u<<0) +#define UX_EHCI_SMASK_1 (0x02u<<0) +#define UX_EHCI_SMASK_2 (0x04u<<0) +#define UX_EHCI_SMASK_3 (0x08u<<0) +#define UX_EHCI_SMASK_4 (0x10u<<0) +#define UX_EHCI_SMASK_5 (0x20u<<0) +#define UX_EHCI_SMASK_6 (0x40u<<0) +#define UX_EHCI_SMASK_7 (0x80u<<0) +#define UX_EHCI_SMASK_INTERVAL_1 (0xFFu<<0) +#define UX_EHCI_SMASK_INTERVAL_2 (0x55u<<0) +#define UX_EHCI_SMASK_INTERVAL_3 (0x11u<<0) +#define UX_EHCI_SMASK_INTERVAL_4 (0x01u<<0) + + +/* EHCI general descriptor type (Buffer pointer page part). */ + +#define UX_EHCI_BP_MASK (0xFFFFF000u) /* 4K align. */ + +/* Define EHCI pointers. */ + +typedef union UX_EHCI_POINTER_UNION { + ULONG value; + VOID *void_ptr; + UCHAR *u8_ptr; + USHORT *u16_ptr; + ULONG *u32_ptr; +} UX_EHCI_POINTER; + +typedef union UX_EHCI_LINK_POINTER_UNION { + ULONG value; + VOID *void_ptr; + UCHAR *u8_ptr; + USHORT *u16_ptr; + ULONG *u32_ptr; + struct UX_EHCI_ED_STRUCT *qh_ptr; + struct UX_EHCI_ED_STRUCT *ed_ptr; + struct UX_EHCI_TD_STRUCT *td_ptr; + struct UX_EHCI_HSISO_TD_STRUCT *itd_ptr; + struct UX_EHCI_FSISO_TD_STRUCT *sitd_ptr; +} UX_EHCI_LINK_POINTER; + +typedef union UX_EHCI_PERIODIC_LINK_POINTER_UNION { + ULONG value; + VOID *void_ptr; + UCHAR *u8_ptr; + USHORT *u16_ptr; + ULONG *u32_ptr; + struct UX_EHCI_ED_STRUCT *qh_ptr; + struct UX_EHCI_ED_STRUCT *ed_ptr; + struct UX_EHCI_HSISO_TD_STRUCT *itd_ptr; + struct UX_EHCI_FSISO_TD_STRUCT *sitd_ptr; +} UX_EHCI_PERIODIC_LINK_POINTER; + + +/* Define the EHCI structure. */ + +typedef struct UX_HCD_EHCI_STRUCT +{ + + struct UX_HCD_STRUCT + *ux_hcd_ehci_hcd_owner; + ULONG ux_hcd_ehci_hcor; + struct UX_EHCI_ED_STRUCT + **ux_hcd_ehci_frame_list; + ULONG *ux_hcd_ehci_base; + UINT ux_hcd_ehci_nb_root_hubs; + struct UX_EHCI_TD_STRUCT + *ux_hcd_ehci_done_head; + struct UX_EHCI_ED_STRUCT + *ux_hcd_ehci_ed_list; + struct UX_EHCI_TD_STRUCT + *ux_hcd_ehci_td_list; + struct UX_EHCI_FSISO_TD_STRUCT + *ux_hcd_ehci_fsiso_td_list; + struct UX_EHCI_HSISO_TD_STRUCT + *ux_hcd_ehci_hsiso_td_list; + struct UX_EHCI_ED_STRUCT + *ux_hcd_ehci_asynch_head_list; + struct UX_EHCI_ED_STRUCT + *ux_hcd_ehci_asynch_first_list; + struct UX_EHCI_ED_STRUCT + *ux_hcd_ehci_asynch_last_list; + struct UX_EHCI_HSISO_TD_STRUCT + *ux_hcd_ehci_hsiso_scan_list; + struct UX_EHCI_FSISO_TD_STRUCT + *ux_hcd_ehci_fsiso_scan_list; + struct UX_TRANSFER_STRUCT + *ux_hcd_ehci_iso_done_transfer_head; + struct UX_TRANSFER_STRUCT + *ux_hcd_ehci_iso_done_transfer_tail; + struct UX_EHCI_ED_STRUCT + *ux_hcd_ehci_interrupt_ed_list; + TX_MUTEX ux_hcd_ehci_periodic_mutex; + TX_SEMAPHORE ux_hcd_ehci_protect_semaphore; + TX_SEMAPHORE ux_hcd_ehci_doorbell_semaphore; + ULONG ux_hcd_ehci_frame_list_size; + ULONG ux_hcd_ehci_interrupt_count; + ULONG ux_hcd_ehci_embedded_tt; +} UX_HCD_EHCI; + + +/* Define EHCI ED structure. */ + +typedef struct UX_EHCI_ED_STRUCT +{ + + struct UX_EHCI_ED_STRUCT + *ux_ehci_ed_queue_head; + ULONG ux_ehci_ed_cap0; + ULONG ux_ehci_ed_cap1; + struct UX_EHCI_TD_STRUCT + *ux_ehci_ed_current_td; + struct UX_EHCI_TD_STRUCT + *ux_ehci_ed_queue_element; + struct UX_EHCI_TD_STRUCT + *ux_ehci_ed_alternate_td; + ULONG ux_ehci_ed_state; + VOID *ux_ehci_ed_bp0; + VOID *ux_ehci_ed_bp1; + VOID *ux_ehci_ed_bp2; + VOID *ux_ehci_ed_bp3; + VOID *ux_ehci_ed_bp4; + /* 12 DWords, 48 bytes QH for controller end. */ + + ULONG ux_ehci_ed_status; + struct UX_EHCI_ED_STRUCT + *ux_ehci_ed_next_ed; + struct UX_EHCI_ED_STRUCT + *ux_ehci_ed_previous_ed; + struct UX_EHCI_TD_STRUCT + *ux_ehci_ed_first_td; + struct UX_EHCI_TD_STRUCT + *ux_ehci_ed_last_td; + union { + struct { /* For anchor. */ + struct UX_EHCI_ED_STRUCT + *ux_ehci_ed_next_anchor; /* + 1 DWord. */ + USHORT ux_ehci_ed_microframe_load[8]; /* + 4 DWords. */ + UCHAR ux_ehci_ed_microframe_ssplit_count[8]; /* + 2 DWords. */ + }; + struct { /* As interrupt ED. */ + struct UX_EHCI_ED_STRUCT + *ux_ehci_ed_anchor; /* + 1 DWord. */ + struct UX_ENDPOINT_STRUCT + *ux_ehci_ed_endpoint; /* + 1 Dword. */ + }; + struct { /* Space: 7 DWord. */ + ULONG ux_ehci_ed_reserved[7]; + }; + }; + /* 24 DWord aligned. */ +} UX_EHCI_ED; + + +/* Define EHCI ED bitmap. */ + +#define UX_EHCI_QH_TYP_ITD 0 +#define UX_EHCI_QH_TYP_QH 2 +#define UX_EHCI_QH_TYP_SITD 4 +#define UX_EHCI_QH_TYP_FSTN 6 + +#define UX_EHCI_QH_T 1 + +#define UX_EHCI_QH_STATIC 0x80000000 +#define UX_EHCI_QH_SSPLIT_SCH_FULL_7 0x40000000 +#define UX_EHCI_QH_SSPLIT_SCH_FULL_6 0x20000000 +#define UX_EHCI_QH_SSPLIT_SCH_FULL_5 0x10000000 +#define UX_EHCI_QH_SSPLIT_SCH_FULL_4 0x08000000 +#define UX_EHCI_QH_SSPLIT_SCH_FULL_3 0x04000000 +#define UX_EHCI_QH_SSPLIT_SCH_FULL_2 0x02000000 +#define UX_EHCI_QH_SSPLIT_SCH_FULL_1 0x01000000 +#define UX_EHCI_QH_SSPLIT_SCH_FULL_0 0x00800000 + +#define UX_EHCI_QH_MPS_LOC 16 +#define UX_EHCI_QH_MPS_MASK 0x07ff0000 +#define UX_EHCI_QH_NCR 0xf0000000 +#define UX_EHCI_QH_CEF 0x08000000 +#define UX_EHCI_QH_ED_AD_LOC 8 +#define UX_EHCI_QH_HBPM 0x40000000 +#define UX_EHCI_QH_HBPM_LOC 30 +#define UX_EHCI_QH_HEAD 0x00008000 + +#define UX_EHCI_QH_HIGH_SPEED 0x00002000 +#define UX_EHCI_QH_LOW_SPEED 0x00001000 + +#define UX_EHCI_QH_HUB_ADDR_LOC 16 +#define UX_EHCI_QH_PORT_NUMBER_LOC 23 +#define UX_EHCI_QH_MULT_LOC 30 +#define UX_EHCI_QH_MULT_MASK 0xc0000000 +#define UX_EHCI_QH_C_MASK 0x00001c00 +#define UX_EHCI_QH_IS_MASK 0x00000001 + +#define UX_EHCI_QH_SMASK_MASK 0x000000FFu +#define UX_EHCI_QH_SMASK_0 0x00000001u +#define UX_EHCI_QH_SMASK_1 0x00000002u +#define UX_EHCI_QH_SMASK_2 0x00000004u +#define UX_EHCI_QH_SMASK_3 0x00000008u +#define UX_EHCI_QH_SMASK_4 0x00000010u +#define UX_EHCI_QH_SMASK_5 0x00000020u +#define UX_EHCI_QH_SMASK_6 0x00000040u +#define UX_EHCI_QH_SMASK_7 0x00000080u + +#define UX_EHCI_QH_DTC 0x00004000 +#define UX_EHCI_QH_TOGGLE 0x80000000 +#define UX_EHCI_LINK_ADDRESS_MASK 0xfffffff0 +#define UX_EHCI_TOGGLE_0 0 +#define UX_EHCI_TOGGLE_1 0x80000000 + +/* Define EHCI TD structure. */ + +typedef struct UX_EHCI_TD_STRUCT +{ + + struct UX_EHCI_TD_STRUCT + *ux_ehci_td_link_pointer; + struct UX_EHCI_TD_STRUCT + *ux_ehci_td_alternate_link_pointer; + ULONG ux_ehci_td_control; + VOID *ux_ehci_td_bp0; + VOID *ux_ehci_td_bp1; + VOID *ux_ehci_td_bp2; + VOID *ux_ehci_td_bp3; + VOID *ux_ehci_td_bp4; + /* 8-DWords, 32-bytes qTD for controller. */ + struct UX_TRANSFER_STRUCT + *ux_ehci_td_transfer_request; + struct UX_EHCI_TD_STRUCT + *ux_ehci_td_next_td_transfer_request; + struct UX_EHCI_ED_STRUCT + *ux_ehci_td_ed; + ULONG ux_ehci_td_length; + ULONG ux_ehci_td_status; + ULONG ux_ehci_td_phase; + ULONG ux_ehci_td_reserved_2[2]; + /* 16-DWord aligned. */ +} UX_EHCI_TD; + + +/* Define EHCI TD bitmap. */ + +#define UX_EHCI_TD_T 1 +#define UX_EHCI_TD_LG_LOC 16 +#define UX_EHCI_TD_LG_MASK 0x7fff +#define UX_EHCI_TD_IOC 0x00008000 +#define UX_EHCI_TD_CERR 0x00000c00 + +#define UX_EHCI_TD_PING 1 +#define UX_EHCI_TD_DO_COMPLETE_SPLIT 2 +#define UX_EHCI_TD_MISSED_MICRO_FRAMES 4 +#define UX_EHCI_TD_TRANSACTION_ERROR 8 +#define UX_EHCI_TD_BABBLE_DETECTED 0x10 +#define UX_EHCI_TD_DATA_BUFFER_ERROR 0x20 +#define UX_EHCI_TD_HALTED 0x40 +#define UX_EHCI_TD_ACTIVE 0x80 + +#define UX_EHCI_PID_OUT 0x00000000 +#define UX_EHCI_PID_IN 0x00000100 +#define UX_EHCI_PID_SETUP 0x00000200 +#define UX_EHCI_PID_MASK 0x00000300 + +#define UX_EHCI_TD_SETUP_PHASE 0x00010000 +#define UX_EHCI_TD_DATA_PHASE 0x00020000 +#define UX_EHCI_TD_STATUS_PHASE 0x00040000 + +/* Define EHCI ISOCHRONOUS TD extension structure. */ + +typedef struct UX_EHCI_HSISO_ED_STRUCT +{ + struct UX_ENDPOINT_STRUCT + *ux_ehci_hsiso_ed_endpoint; + struct UX_EHCI_ED_STRUCT + *ux_ehci_hsiso_ed_anchor; + struct UX_TRANSFER_STRUCT + *ux_ehci_hsiso_ed_transfer_head; + struct UX_TRANSFER_STRUCT + *ux_ehci_hsiso_ed_transfer_tail; + struct UX_TRANSFER_STRUCT + *ux_ehci_hsiso_ed_transfer_first_new; + struct UX_EHCI_HSISO_TD_STRUCT + *ux_ehci_hsiso_ed_fr_td[4]; + UCHAR ux_ehci_hsiso_ed_frindex; /* 1st usable micro-frame. */ + UCHAR ux_ehci_hsiso_ed_frinterval; /* Micro-frame interval. */ + UCHAR ux_ehci_hsiso_ed_frinterval_shift; /* Shift for micro-frame interval. */ + UCHAR ux_ehci_hsiso_ed_nb_tds; + USHORT ux_ehci_hsiso_ed_frstart; /* Start micro-frame. */ + USHORT ux_ehci_hsiso_ed_frload; + USHORT ux_ehci_hsiso_ed_fr_hc; /* Micro-frame HC process count. */ + USHORT ux_ehci_hsiso_ed_fr_sw; /* Micro-frame SW load count. */ +} UX_EHCI_HSISO_ED; + +/* Define EHCI ISOCHRONOUS TD structure. */ + +typedef struct UX_EHCI_HSISO_TD_STRUCT +{ + + union UX_EHCI_PERIODIC_LINK_POINTER_UNION + ux_ehci_hsiso_td_next_lp; + ULONG ux_ehci_hsiso_td_control[8]; + VOID *ux_ehci_hsiso_td_bp[7]; + /* 16 DWords, 64-bytes iTD for controller end. */ + UCHAR ux_ehci_hsiso_td_status; + UCHAR ux_ehci_hsiso_td_frload; /* REQ load map. */ + USHORT ux_ehci_hsiso_td_max_trans_size; + union UX_EHCI_PERIODIC_LINK_POINTER_UNION + ux_ehci_hsiso_td_previous_lp; + struct UX_EHCI_HSISO_TD_STRUCT + *ux_ehci_hsiso_td_next_scan_td; + struct UX_EHCI_HSISO_TD_STRUCT + *ux_ehci_hsiso_td_previous_scan_td; + struct UX_TRANSFER_STRUCT + *ux_ehci_hsiso_td_fr_transfer[3]; + struct UX_EHCI_HSISO_ED_STRUCT + *ux_ehci_hsiso_td_ed; + /* 24 DWord aligned. */ +} UX_EHCI_HSISO_TD; + + +/* Next Link Pointer(LP). */ + +#define UX_EHCI_HSISO_LP_MASK UX_EHCI_LP_MASK + +#define UX_EHCI_HSISO_TYP_MASK UX_EHCI_TYP_MASK +#define UX_EHCI_HSISO_TYP_ITD UX_EHCI_TYP_ITD +#define UX_EHCI_HSISO_TYP_QH UX_EHCI_TYP_QH +#define UX_EHCI_HSISO_TYP_SITD UX_EHCI_TYP_SITD +#define UX_EHCI_HSISO_TYP_FSTN UX_EHCI_TYP_FSTN + +#define UX_EHCI_HSISO_T UX_EHCI_T + +/* Transaction Status and Control. */ + +#define UX_EHCI_HSISO_STATUS_MASK 0xF0000000u +#define UX_EHCI_HSISO_STATUS_ACTIVE 0x80000000u +#define UX_EHCI_HSISO_STATUS_DATA_BUFFER_ERR 0x40000000u +#define UX_EHCI_HSISO_STATUS_BABBLE_DETECTED 0x20000000u +#define UX_EHCI_HSISO_STATUS_XACT_ERR 0x10000000u + +#define UX_EHCI_HSISO_XACT_LENGTH_MASK 0x0FFF0000u +#define UX_EHCI_HSISO_XACT_LENGTH_SHIFT 16 +#define UX_EHCI_HSISO_XACT_LENGTH_VALUE_MAX 0xC00 + +#define UX_EHCI_HSISO_IOC 0x00008000u +#define UX_EHCI_HSISO_IOC_SHIFT 15 + +#define UX_EHCI_HSISO_PG_MASK 0x00007000u +#define UX_EHCI_HSISO_PG_SHIFT 12 + +#define UX_EHCI_HSISO_XACT_OFFSET_MASK 0x00000FFFu + +/* Buffer Page Pointer List. */ + +#define UX_EHCI_HSISO_BP_MASK UX_EHCI_BP_MASK + +/* BP0 */ + +#define UX_EHCI_HSISO_ENDPT_MASK UX_EHCI_ENDPT_MASK +#define UX_EHCI_HSISO_ENDPT_SHIFT UX_EHCI_ENDPT_SHIFT + +#define UX_EHCI_HSISO_DEVICE_ADDRESS_MASK UX_EHCI_DEVICE_ADDRESS_MASK + +/* BP1 */ + +#define UX_EHCI_HSISO_DIRECTION (0x1u << 11) +#define UX_EHCI_HSISO_DIRECTION_IN UX_EHCI_HSISO_DIRECTION +#define UX_EHCI_HSISO_DIRECTION_OUT 0 + +#define UX_EHCI_HSISO_MAX_PACKET_SIZE_MASK 0x000007FFu +#define UX_EHCI_HSISO_MAX_PACKET_SIZE_MAX 0x00000400 + +/* BP2 */ + +#define UX_EHCI_HSISO_MULTI_MASK 0x00000003u +#define UX_EHCI_HSISO_MULTI_ONE 1 +#define UX_EHCI_HSISO_MULTI_TWO 2 +#define UX_EHCI_HSISO_MULTI_THREE 3 + +/* Define EHCI FS ISOCHRONOUS TD structure. */ + +typedef struct UX_EHCI_FSISO_TD_STRUCT +{ + union UX_EHCI_PERIODIC_LINK_POINTER_UNION + ux_ehci_fsiso_td_next_lp; + ULONG ux_ehci_fsiso_td_cap0; /* endpoint */ + ULONG ux_ehci_fsiso_td_cap1; /* uFrame schedule */ + ULONG ux_ehci_fsiso_td_state; + VOID *ux_ehci_fsiso_td_bp[2]; + VOID *ux_ehci_fsiso_td_back_pointer; + /* 7 DWords, 28-bytes siTD for controller end. */ + + UCHAR ux_ehci_fsiso_td_status; + UCHAR ux_ehci_fsiso_td_frindex; + UCHAR ux_ehci_fsiso_td_nb_ed_tds; + UCHAR reserved[1]; + struct UX_ENDPOINT_STRUCT + *ux_ehci_fsiso_td_endpoint; + struct UX_TRANSFER_STRUCT + *ux_ehci_fsiso_td_transfer_head; + struct UX_TRANSFER_STRUCT + *ux_ehci_fsiso_td_transfer_tail; + union UX_EHCI_PERIODIC_LINK_POINTER_UNION + ux_ehci_fsiso_td_previous_lp; + struct UX_EHCI_FSISO_TD_STRUCT + *ux_ehci_fsiso_td_next_scan_td; + struct UX_EHCI_FSISO_TD_STRUCT + *ux_ehci_fsiso_td_previous_scan_td; + struct UX_EHCI_ED_STRUCT + *ux_ehci_fsiso_td_anchor; + struct UX_EHCI_TD_STRUCT + *ux_ehci_fsiso_td_next_ed_td; + /* 16-DWord aligned. */ +} UX_EHCI_FSISO_TD; + +/* Next Link Pointer (LP). */ + +#define UX_EHCI_FSISO_LP_MASK UX_EHCI_LP_MASK + +#define UX_EHCI_FSISO_TYP_MASK UX_EHCI_TYP_MASK +#define UX_EHCI_FSISO_TYP_ITD UX_EHCI_TYP_ITD +#define UX_EHCI_FSISO_TYP_QH UX_EHCI_TYP_QH +#define UX_EHCI_FSISO_TYP_SITD UX_EHCI_TYP_SITD +#define UX_EHCI_FSISO_TYP_FSTN UX_EHCI_TYP_FSTN + +#define UX_EHCI_FSISO_T UX_EHCI_T + +/* Endpoint Capabilities/Characteristics. */ + +#define UX_EHCI_FSISO_DIRECTION 0x80000000u +#define UX_EHCI_FSISO_DIRECTION_IN 0x80000000u +#define UX_EHCI_FSISO_DIRECTION_OUT 0x00000000 + +#define UX_EHCI_FSISO_PORT_NUMBER_MASK 0x7F000000u +#define UX_EHCI_FSISO_PORT_NUMBER_SHIFT 24 + +#define UX_EHCI_FSISO_HUB_ADDRESS_MASK 0x003F0000u +#define UX_EHCI_FSISO_HUB_ADDRESS_SHIFT 16 + +#define UX_EHCI_FSISO_ENDPT_MASK UX_EHCI_ENDPT_MASK +#define UX_EHCI_FSISO_ENDPT_SHIFT UX_EHCI_ENDPT_SHIFT + +#define UX_EHCI_FSISO_DEVICE_ADDRESS_MASK UX_EHCI_DEVICE_ADDRESS_MASK + +/* Micro-frame Schedule Control. */ + +#define UX_EHCI_FSISO_UFRAME_CMASK_MASK UX_EHCI_CMASK_MASK +#define UX_EHCI_FSISO_UFRAME_CMASK_0 UX_EHCI_CMASK_0 +#define UX_EHCI_FSISO_UFRAME_CMASK_1 UX_EHCI_CMASK_1 +#define UX_EHCI_FSISO_UFRAME_CMASK_2 UX_EHCI_CMASK_2 +#define UX_EHCI_FSISO_UFRAME_CMASK_3 UX_EHCI_CMASK_3 +#define UX_EHCI_FSISO_UFRAME_CMASK_4 UX_EHCI_CMASK_4 +#define UX_EHCI_FSISO_UFRAME_CMASK_5 UX_EHCI_CMASK_5 +#define UX_EHCI_FSISO_UFRAME_CMASK_6 UX_EHCI_CMASK_6 +#define UX_EHCI_FSISO_UFRAME_CMASK_7 UX_EHCI_CMASK_7 + +#define UX_EHCI_FSISO_UFRAME_SMASK_MASK UX_EHCI_SMASK_MASK +#define UX_EHCI_FSISO_UFRAME_SMASK_0 UX_EHCI_SMASK_0 +#define UX_EHCI_FSISO_UFRAME_SMASK_1 UX_EHCI_SMASK_1 +#define UX_EHCI_FSISO_UFRAME_SMASK_2 UX_EHCI_SMASK_2 +#define UX_EHCI_FSISO_UFRAME_SMASK_3 UX_EHCI_SMASK_3 +#define UX_EHCI_FSISO_UFRAME_SMASK_4 UX_EHCI_SMASK_4 +#define UX_EHCI_FSISO_UFRAME_SMASK_5 UX_EHCI_SMASK_5 +#define UX_EHCI_FSISO_UFRAME_SMASK_6 UX_EHCI_SMASK_6 +#define UX_EHCI_FSISO_UFRAME_SMASK_7 UX_EHCI_SMASK_7 + +/* Transfer State. */ + +/* Transfer Status and Control. */ + +#define UX_EHCI_FSISO_IOC 0x80000000u + +#define UX_EHCI_FSISO_P 0x40000000u + +#define UX_EHCI_FSISO_TOTAL_BYTES_MASK 0x03FF0000u +#define UX_EHCI_FSISO_TOTAL_BYTES_SHIFT 16 +#define UX_EHCI_FSISO_TOTAL_BYTES_MAX_VALUE 1023 + +#define UX_EHCI_FSISO_CPROMASK_MASK 0x0000FF00u +#define UX_EHCI_FSISO_CPROMASK_SHIFT 8 + +#define UX_EHCI_FSISO_STATUS_MASK 0x000000FFu +#define UX_EHCI_FSISO_STATUS_ACTIVE 0x00000080u +#define UX_EHCI_FSISO_STATUS_ERR 0x00000040u +#define UX_EHCI_FSISO_STATUS_DATA_BUFFER_ERR 0x00000020u +#define UX_EHCI_FSISO_STATUS_BABBLE_DETECTED 0x00000010u +#define UX_EHCI_FSISO_STATUS_XACTERR 0x00000008u +#define UX_EHCI_FSISO_STATUS_MISSED_MFRAME 0x00000004u + +#define UX_EHCI_FSISO_STATUS_SPLIT_STATE_MASK 0x00000002u +#define UX_EHCI_FSISO_STATUS_SPLIT_STATE_DO_START 0x00000000u +#define UX_EHCI_FSISO_STATUS_SPLIT_STATE_DO_COMPLETE 0x00000002u + +/* Buffer Page Pointer List. */ + +#define UX_EHCI_FSISO_BP_MASK UX_EHCI_BP_MASK + +/* BP0 */ + +#define UX_EHCI_FSISO_CURRENT_OFFSET_MASK 0x00000FFFu + +/* BP1 */ + +#define UX_EHCI_FSISO_TP_MASK 0x0000000Cu +#define UX_EHCI_FSISO_TP_ALL 0x00000000u +#define UX_EHCI_FSISO_TP_BEGIN 0x00000004u +#define UX_EHCI_FSISO_TP_MID 0x00000008u +#define UX_EHCI_FSISO_TP_END 0x0000000Cu + +#define UX_EHCI_FSISO_TCOUNT_MASK 0x00000007u +#define UX_EHCI_FSISO_TCOUNT_MAX 6 + + +/* Define EHCI function prototypes. */ + +void _ux_hcd_ehci_periodic_descriptor_link(VOID* prev, VOID* prev_next, VOID* next_prev, VOID* next); +UX_EHCI_TD *_ux_hcd_ehci_asynch_td_process(UX_EHCI_ED *ed, UX_EHCI_TD *td); +UX_EHCI_HSISO_TD *_ux_hcd_ehci_hsisochronous_tds_process(UX_HCD_EHCI *hcd_ehci, UX_EHCI_HSISO_TD* itd); +UX_EHCI_FSISO_TD *_ux_hcd_ehci_fsisochronous_tds_process(UX_HCD_EHCI *hcd_ehci, UX_EHCI_FSISO_TD* sitd); +UINT _ux_hcd_ehci_asynchronous_endpoint_create(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint); +UINT _ux_hcd_ehci_asynchronous_endpoint_destroy(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint); +UINT _ux_hcd_ehci_controller_disable(UX_HCD_EHCI *hcd_ehci); +VOID _ux_hcd_ehci_done_queue_process(UX_HCD_EHCI *hcd_ehci); +VOID _ux_hcd_ehci_door_bell_wait(UX_HCD_EHCI *hcd_ehci); +UINT _ux_hcd_ehci_ed_clean(UX_EHCI_ED *ed); +UX_EHCI_ED *_ux_hcd_ehci_ed_obtain(UX_HCD_EHCI *hcd_ehci); +UINT _ux_hcd_ehci_endpoint_reset(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint); +UINT _ux_hcd_ehci_entry(UX_HCD *hcd, UINT function, VOID *parameter); +UINT _ux_hcd_ehci_frame_number_get(UX_HCD_EHCI *hcd_ehci, ULONG *frame_number); +VOID _ux_hcd_ehci_frame_number_set(UX_HCD_EHCI *hcd_ehci, ULONG frame_number); +UX_EHCI_FSISO_TD *_ux_hcd_ehci_fsisochronous_td_obtain(UX_HCD_EHCI *hcd_ehci); +UX_EHCI_HSISO_TD *_ux_hcd_ehci_hsisochronous_td_obtain(UX_HCD_EHCI *hcd_ehci); +UINT _ux_hcd_ehci_initialize(UX_HCD *hcd); +UINT _ux_hcd_ehci_interrupt_endpoint_create(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint); +UINT _ux_hcd_ehci_interrupt_endpoint_destroy(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint); +VOID _ux_hcd_ehci_interrupt_handler(VOID); +UINT _ux_hcd_ehci_isochronous_endpoint_create(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint); +UINT _ux_hcd_ehci_isochronous_endpoint_destroy(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint); +UX_EHCI_ED *_ux_hcd_ehci_least_traffic_list_get(UX_HCD_EHCI *hcd_ehci, ULONG microframe_load[8], ULONG microframe_ssplit_count[8]); +UX_EHCI_ED *_ux_hcd_ehci_poll_rate_entry_get(UX_HCD_EHCI *hcd_ehci, UX_EHCI_ED *ed_list, ULONG poll_depth); +VOID _ux_hcd_ehci_next_td_clean(UX_EHCI_TD *td); +UINT _ux_hcd_ehci_periodic_tree_create(UX_HCD_EHCI *hcd_ehci); +UINT _ux_hcd_ehci_port_disable(UX_HCD_EHCI *hcd_ehci, ULONG port_index); +UINT _ux_hcd_ehci_port_reset(UX_HCD_EHCI *hcd_ehci, ULONG port_index); +UINT _ux_hcd_ehci_port_resume(UX_HCD_EHCI *hcd_ehci, UINT port_index); +ULONG _ux_hcd_ehci_port_status_get(UX_HCD_EHCI *hcd_ehci, ULONG port_index); +UINT _ux_hcd_ehci_port_suspend(UX_HCD_EHCI *hcd_ehci, ULONG port_index); +UINT _ux_hcd_ehci_power_down_port(UX_HCD_EHCI *hcd_ehci, ULONG port_index); +UINT _ux_hcd_ehci_power_on_port(UX_HCD_EHCI *hcd_ehci, ULONG port_index); +VOID _ux_hcd_ehci_power_root_hubs(UX_HCD_EHCI *hcd_ehci); +ULONG _ux_hcd_ehci_register_read(UX_HCD_EHCI *hcd_ehci, ULONG ehci_register); +VOID _ux_hcd_ehci_register_write(UX_HCD_EHCI *hcd_ehci, ULONG ehci_register, ULONG value); +UX_EHCI_TD *_ux_hcd_ehci_regular_td_obtain(UX_HCD_EHCI *hcd_ehci); +UINT _ux_hcd_ehci_request_bulk_transfer(UX_HCD_EHCI *hcd_ehci, UX_TRANSFER *transfer_request); +UINT _ux_hcd_ehci_request_control_transfer(UX_HCD_EHCI *hcd_ehci, UX_TRANSFER *transfer_request); +UINT _ux_hcd_ehci_request_interrupt_transfer(UX_HCD_EHCI *hcd_ehci, UX_TRANSFER *transfer_request); +UINT _ux_hcd_ehci_request_isochronous_transfer(UX_HCD_EHCI *hcd_ehci, UX_TRANSFER *transfer_request); +UINT _ux_hcd_ehci_request_transfer(UX_HCD_EHCI *hcd_ehci, UX_TRANSFER *transfer_request); +UINT _ux_hcd_ehci_request_transfer_add(UX_HCD_EHCI *hcd_ehci, UX_EHCI_ED *ed, ULONG phase, ULONG pid, + ULONG toggle, UCHAR * buffer_address, ULONG buffer_length, UX_TRANSFER *transfer_request); +UINT _ux_hcd_ehci_transfer_abort(UX_HCD_EHCI *hcd_ehci,UX_TRANSFER *transfer_request); +VOID _ux_hcd_ehci_transfer_request_process(UX_TRANSFER *transfer_request); + +#define ux_hcd_ehci_initialize _ux_hcd_ehci_initialize +#define ux_hcd_ehci_interrupt_handler _ux_hcd_ehci_interrupt_handler + +#endif + diff --git a/common/usbx_host_controllers/inc/ux_hcd_ohci.h b/common/usbx_host_controllers/inc/ux_hcd_ohci.h new file mode 100644 index 0000000..2463440 --- /dev/null +++ b/common/usbx_host_controllers/inc/ux_hcd_ohci.h @@ -0,0 +1,393 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_hcd_ohci.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX host OHCI Controller. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_HCD_OHCI_H +#define UX_HCD_OHCI_H + + +/* Define generic OHCI constants. */ + +#define UX_OHCI_CONTROLLER 1 +#define UX_OHCI_MAX_PAYLOAD 4096 +#define UX_OHCI_FRAME_DELAY 4 + + +/* Define OHCI HCOR register mapping. */ + +#define OHCI_HC_REVISION 0x00 +#define OHCI_HC_CONTROL 0x01 +#define OHCI_HC_COMMAND_STATUS 0x02 +#define OHCI_HC_INTERRUPT_STATUS 0x03 +#define OHCI_HC_INTERRUPT_ENABLE 0x04 +#define OHCI_HC_INTERRUPT_DISABLE 0x05 +#define OHCI_HC_HCCA 0x06 +#define OHCI_HC_PERIOD_CURRENT_ED 0x07 +#define OHCI_HC_CONTROL_HEAD_ED 0x08 +#define OHCI_HC_CONTROL_CURRENT_ED 0x09 +#define OHCI_HC_BULK_HEAD_ED 0x0a +#define OHCI_HC_BULK_CURRENT_ED 0x0b +#define OHCI_HC_DONE_HEAD 0x0c +#define OHCI_HC_FM_INTERVAL 0x0d +#define OHCI_HC_FM_REMAINING 0x0e +#define OHCI_HC_FM_NUMBER 0x0f +#define OHCI_HC_PERIODIC_START 0x10 +#define OHCI_HC_LS_THRESHOLD 0x11 +#define OHCI_HC_RH_DESCRIPTOR_A 0x12 +#define OHCI_HC_RH_DESCRIPTOR_B 0x13 +#define OHCI_HC_RH_STATUS 0x14 +#define OHCI_HC_RH_PORT_STATUS 0x15 + + +/* Define OHCI control register values. */ + +#define OHCI_HC_CR_CBSR_0 0x00000000 +#define OHCI_HC_CR_CBSR_1 0x00000001 +#define OHCI_HC_CR_CBSR_2 0x00000002 +#define OHCI_HC_CR_CBSR_3 0x00000003 +#define OHCI_HC_CR_PLE 0x00000004 +#define OHCI_HC_CR_IE 0x00000008 +#define OHCI_HC_CR_CLE 0x00000010 +#define OHCI_HC_CR_BLE 0x00000020 +#define OHCI_HC_CR_RESET 0x00000000 +#define OHCI_HC_CR_RESUME 0x00000040 +#define OHCI_HC_CR_OPERATIONAL 0x00000080 +#define OHCI_HC_CR_SUSPEND 0x000000c0 +#define OHCI_HC_CR_IR 0x00000100 +#define OHCI_HC_CR_RWC 0x00000200 +#define OHCI_HC_CR_RWE 0x00000400 + +#define OHCI_HC_CONTROL_VALUE (OHCI_HC_CR_CBSR_3 | OHCI_HC_CR_OPERATIONAL | OHCI_HC_CR_PLE | OHCI_HC_CR_IE | OHCI_HC_CR_CLE | OHCI_HC_CR_BLE) + + +/* Define OHCI HCOR command/status bitmaps. */ + +#define OHCI_HC_CS_HCR 0x00000001 +#define OHCI_HC_CS_CLF 0x00000002 +#define OHCI_HC_CS_BLF 0x00000004 + + +#define OHCI_HC_RH_PSM 0x00000100 +#define OHCI_HC_RH_NPS 0x00000200 +#define OHCI_HC_RH_DT 0x00000400 +#define OHCI_HC_RH_OCPM 0x00000800 +#define OHCI_HC_RH_NOCP 0x00001000 +#define OHCI_HC_RH_POTPGT 24 + +#define OHCI_HC_RS_LPS 0x00000001 +#define OHCI_HC_RS_OCI 0x00000002 +#define OHCI_HC_RS_DRWE 0x00008000 +#define OHCI_HC_RS_LPSC 0x00010000 +#define OHCI_HC_RS_OCIC 0x00020000 +#define OHCI_HC_RS_CRWE 0x80000000 + +#define OHCI_HC_PS_CCS 0x00000001 +#define OHCI_HC_PS_CPE 0x00000001 +#define OHCI_HC_PS_PES 0x00000002 +#define OHCI_HC_PS_PSS 0x00000004 +#define OHCI_HC_PS_POCI 0x00000008 +#define OHCI_HC_PS_PRS 0x00000010 +#define OHCI_HC_PS_PPS 0x00000100 +#define OHCI_HC_PS_LSDA 0x00000200 +#define OHCI_HC_PS_CSC 0x00010000 +#define OHCI_HC_PS_PESC 0x00020000 +#define OHCI_HC_PS_PSSC 0x00040000 +#define OHCI_HC_PS_OCIC 0x00080000 +#define OHCI_HC_PS_PRSC 0x00100000 + + +/* Define OHCI interrupt status register definitions. */ + +#define OHCI_HC_INT_SO 0x00000001 +#define OHCI_HC_INT_WDH 0x00000002 +#define OHCI_HC_INT_SF 0x00000004 +#define OHCI_HC_INT_RD 0x00000008 +#define OHCI_HC_INT_UE 0x00000010 +#define OHCI_HC_INT_FNO 0x00000020 +#define OHCI_HC_INT_RHSC 0x00000040 +#define OHCI_HC_INT_OC 0x40000000 + +#define OHCI_HC_INT_MIE 0x80000000 + + +#define OHCI_HC_INTERRUPT_ENABLE_NORMAL (OHCI_HC_INT_WDH | OHCI_HC_INT_RD | OHCI_HC_INT_UE | OHCI_HC_INT_RHSC | OHCI_HC_INT_MIE) + +#define OHCI_HC_INTERRUPT_DISABLE_ALL (OHCI_HC_INT_SO | \ + OHCI_HC_INT_WDH | \ + OHCI_HC_INT_SF | \ + OHCI_HC_INT_RD | \ + OHCI_HC_INT_UE | \ + OHCI_HC_INT_FNO | \ + OHCI_HC_INT_RHSC | \ + OHCI_HC_INT_OC | \ + OHCI_HC_INT_MIE) + + +/* Define OHCI frame interval definition. */ + +#define OHCI_HC_FM_INTERVAL_CLEAR 0x8000ffff +#define OHCI_HC_FM_INTERVAL_SET 0x27780000 + + +/* Define OHCI static definition. */ + +#define UX_OHCI_AVAILABLE_BANDWIDTH 6000 +#define UX_OHCI_INIT_DELAY 1000 +#define UX_OHCI_RESET_RETRY 1000 +#define UX_OHCI_RESET_DELAY 10 +#define UX_OHCI_PORT_RESET_RETRY 10 +#define UX_OHCI_PORT_RESET_DELAY 10 + + +/* Define OHCI initialization values. */ + +#define UX_OHCI_COMMAND_STATUS_RESET 0 +#define UX_OHCI_INIT_RESET_DELAY 10 +#define UX_OHCI_HC_PERIODIC_START_DEFAULT 0x00003e67 + +/* Define OHCI completion code errors. */ + +#define UX_OHCI_NO_ERROR 0x00 +#define UX_OHCI_ERROR_CRC 0x01 +#define UX_OHCI_ERROR_BIT_STUFFING 0x02 +#define UX_OHCI_ERROR_DATA_TOGGLE 0x03 +#define UX_OHCI_ERROR_STALL 0x04 +#define UX_OHCI_ERROR_DEVICE_NOT_RESPONDING 0x05 +#define UX_OHCI_ERROR_PID_FAILURE 0x06 +#define UX_OHCI_ERROR_PID_UNEXPECTED 0x07 +#define UX_OHCI_ERROR_DATA_OVERRRUN 0x08 +#define UX_OHCI_ERROR_DATA_UNDERRUN 0x09 +#define UX_OHCI_ERROR_BUFFER_OVERRRUN 0x0c +#define UX_OHCI_ERROR_BUFFER_UNDERRUN 0x0d +#define UX_OHCI_NOT_ACCESSED 0x0e + + +/* Define OHCI HCCA structure. */ + +typedef struct UX_HCD_OHCI_HCCA_STRUCT +{ + + struct UX_OHCI_ED_STRUCT + *ux_hcd_ohci_hcca_ed[32]; + USHORT ux_hcd_ohci_hcca_frame_number; + USHORT ux_hcd_ohci_hcca_reserved1; + struct UX_OHCI_TD_STRUCT + *ux_hcd_ohci_hcca_done_head; + UCHAR ux_hcd_ohci_hcca_reserved2[116]; +} UX_HCD_OHCI_HCCA; + + +/* Define OHCI HCD structure. */ + +typedef struct UX_HCD_OHCI_STRUCT +{ + + struct UX_HCD_STRUCT + *ux_hcd_ohci_hcd_owner; + struct UX_HCD_OHCI_HCCA_STRUCT + *ux_hcd_ohci_hcca; + ULONG *ux_hcd_ohci_hcor; + UINT ux_hcd_ohci_nb_root_hubs; + struct UX_OHCI_TD_STRUCT + *ux_hcd_ohci_done_head; + struct UX_OHCI_ED_STRUCT + *ux_hcd_ohci_ed_list; + struct UX_OHCI_TD_STRUCT + *ux_hcd_ohci_td_list; + struct UX_OHCI_ISO_TD_STRUCT + *ux_hcd_ohci_iso_td_list; +} UX_HCD_OHCI; + + +/* Define OHCI ED structure. */ + +typedef struct UX_OHCI_ED_STRUCT +{ + + ULONG ux_ohci_ed_dw0; + struct UX_OHCI_TD_STRUCT + *ux_ohci_ed_tail_td; + struct UX_OHCI_TD_STRUCT + *ux_ohci_ed_head_td; + struct UX_OHCI_ED_STRUCT + *ux_ohci_ed_next_ed; + struct UX_OHCI_ED_STRUCT + *ux_ohci_ed_previous_ed; + ULONG ux_ohci_ed_status; + struct UX_ENDPOINT_STRUCT + *ux_ohci_ed_endpoint; + ULONG ux_ohci_ed_frame; +} UX_OHCI_ED; + + +/* Define OHCI ED bitmap. */ + +#define UX_OHCI_ED_LOW_SPEED 0x00002000 +#define UX_OHCI_ED_SKIP 0x00004000 +#define UX_OHCI_ED_ISOCHRONOUS 0x00008000 +#define UX_OHCI_ED_MPS 0x0000ffff + +#define UX_OHCI_ED_HALTED 0x00000001 +#define UX_OHCI_ED_TOGGLE_CARRY 0x00000002 +#define UX_OHCI_ED_MASK_TD (~0x00000003) + +#define UX_OHCI_ED_OUT 0x800 +#define UX_OHCI_ED_IN 0x1000 + + +/* Define OHCI TD structure. */ + +typedef struct UX_OHCI_TD_STRUCT +{ + ULONG ux_ohci_td_dw0; + UCHAR * ux_ohci_td_cbp; + struct UX_OHCI_TD_STRUCT + *ux_ohci_td_next_td; + UCHAR * ux_ohci_td_be; + ULONG ux_ohci_td_reserved_1[4]; + struct UX_TRANSFER_STRUCT + *ux_ohci_td_transfer_request; + struct UX_OHCI_TD_STRUCT + *ux_ohci_td_next_td_transfer_request; + struct UX_OHCI_ED_STRUCT + *ux_ohci_td_ed; + ULONG ux_ohci_td_length; + ULONG ux_ohci_td_status; + ULONG ux_ohci_td_reserved_2[3]; +} UX_OHCI_TD; + + +/* Define OHCI TD bitmap. */ + +#define UX_OHCI_TD_OUT 0x00080000 +#define UX_OHCI_TD_IN 0x00100000 +#define UX_OHCI_TD_DEFAULT_DW0 0xf0000000 +#define UX_OHCI_TD_DATA0 0x02000000 +#define UX_OHCI_TD_DATA1 0x03000000 +#define UX_OHCI_TD_R 0x00040000 + +#define UX_OHCI_TD_SETUP_PHASE 0x00010000 +#define UX_OHCI_TD_DATA_PHASE 0x00020000 +#define UX_OHCI_TD_STATUS_PHASE 0x00040000 +#define UX_OHCI_TD_CC 28 + + +/* Define OHCI ISOCHRONOUS TD structure. */ + +typedef struct UX_OHCI_ISO_TD_STRUCT +{ + + ULONG ux_ohci_iso_td_dw0; + UCHAR * ux_ohci_iso_td_bp0; + struct UX_OHCI_TD_STRUCT + *ux_ohci_iso_td_next_td; + UCHAR * ux_ohci_iso_td_be; + USHORT ux_ohci_iso_td_offset_psw[8]; + struct UX_TRANSFER_STRUCT + *ux_ohci_iso_td_transfer_request; + struct UX_OHCI_TD_STRUCT + *ux_ohci_iso_td_next_td_transfer_request; + struct UX_OHCI_ED_STRUCT + *ux_ohci_iso_td_ed; + ULONG ux_ohci_iso_td_length; + ULONG ux_ohci_iso_td_status; + ULONG ux_ohci_iso_td_reserved[3]; +} UX_OHCI_ISO_TD; + + +/* Define OHCI ISOCHRONOUS TD bitmap. */ + +#define UX_OHCI_ISO_TD_BASE 0xfffff000 +#define UX_OHCI_ISO_TD_OFFSET 0x00000fff +#define UX_OHCI_ISO_TD_PSW_CC 0x0000e000 +#define UX_OHCI_ISO_TD_FC 24 + + +/* Define OHCI function prototypes. */ + +UINT _ux_hcd_ohci_asynchronous_endpoint_create(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint); +UINT _ux_hcd_ohci_asynchronous_endpoint_destroy(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint); +UINT _ux_hcd_ohci_controller_disable(UX_HCD_OHCI *hcd_ohci); +VOID _ux_hcd_ohci_done_queue_process(UX_HCD_OHCI *hcd_ohci); +UX_OHCI_ED *_ux_hcd_ohci_ed_obtain(UX_HCD_OHCI *hcd_ohci); +UINT _ux_hcd_ohci_endpoint_error_clear(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint); +UINT _ux_hcd_ohci_endpoint_reset(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint); +UINT _ux_hcd_ohci_entry(UX_HCD *hcd, UINT function, VOID *parameter); +UINT _ux_hcd_ohci_frame_number_get(UX_HCD_OHCI *hcd_ohci, ULONG *frame_number); +VOID _ux_hcd_ohci_frame_number_set(UX_HCD_OHCI *hcd_ohci, ULONG frame_number); +UINT _ux_hcd_ohci_initialize(UX_HCD *hcd); +UINT _ux_hcd_ohci_interrupt_endpoint_create(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint); +VOID _ux_hcd_ohci_interrupt_handler(VOID); +UINT _ux_hcd_ohci_isochronous_endpoint_create(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint); +UX_OHCI_ISO_TD *_ux_hcd_ohci_isochronous_td_obtain(UX_HCD_OHCI *hcd_ohci); +UX_OHCI_ED *_ux_hcd_ohci_least_traffic_list_get(UX_HCD_OHCI *hcd_ohci); +VOID _ux_hcd_ohci_next_td_clean(UX_OHCI_TD *td); +UINT _ux_hcd_ohci_periodic_endpoint_destroy(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint); +UINT _ux_hcd_ohci_periodic_tree_create(UX_HCD_OHCI *hcd_ohci); +UINT _ux_hcd_ohci_port_disable(UX_HCD_OHCI *hcd_ohci, ULONG port_index); +UINT _ux_hcd_ohci_port_enable(UX_HCD_OHCI *hcd_ohci, ULONG port_index); +UINT _ux_hcd_ohci_port_reset(UX_HCD_OHCI *hcd_ohci, ULONG port_index); +UINT _ux_hcd_ohci_port_resume(UX_HCD_OHCI *hcd_ohci, UINT port_index); +ULONG _ux_hcd_ohci_port_status_get(UX_HCD_OHCI *hcd_ohci, ULONG port_index); +UINT _ux_hcd_ohci_port_suspend(UX_HCD_OHCI *hcd_ohci, ULONG port_index); +UINT _ux_hcd_ohci_power_down_port(UX_HCD_OHCI *hcd_ohci, ULONG port_index); +UINT _ux_hcd_ohci_power_on_port(UX_HCD_OHCI *hcd_ohci, ULONG port_index); +VOID _ux_hcd_ohci_power_root_hubs(UX_HCD_OHCI *hcd_ohci); +ULONG _ux_hcd_ohci_register_read(UX_HCD_OHCI *hcd_ohci, ULONG ohci_register); +VOID _ux_hcd_ohci_register_write(UX_HCD_OHCI *hcd_ohci, ULONG ohci_register, ULONG value); +UX_OHCI_TD *_ux_hcd_ohci_regular_td_obtain(UX_HCD_OHCI *hcd_ohci); +UINT _ux_hcd_ohci_request_bulk_transfer(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request); +UINT _ux_hcd_ohci_request_control_transfer(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request); +UINT _ux_hcd_ohci_request_interrupt_transfer(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request); +UINT _ux_hcd_ohci_request_isochronous_transfer(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request); +UINT _ux_hcd_ohci_request_transfer(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request); +UINT _ux_hcd_ohci_transfer_abort(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request); +VOID _ux_hcd_ohci_transfer_request_process(UX_TRANSFER *transfer_request); + +#define ux_hcd_ohci_initialize _ux_hcd_ohci_initialize +#define ux_hcd_ohci_interrupt_handler _ux_hcd_ohci_interrupt_handler + +#endif + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_asynch_td_process.c b/common/usbx_host_controllers/src/ux_hcd_ehci_asynch_td_process.c new file mode 100644 index 0000000..b0f1a58 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_asynch_td_process.c @@ -0,0 +1,209 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_asynch_td_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the isochronous, periodic and asynchronous */ +/* lists in search for transfers that occurred in the past */ +/* (micro-)frame. */ +/* */ +/* INPUT */ +/* */ +/* ed Pointer to ED */ +/* td Pointer to TD */ +/* */ +/* OUTPUT */ +/* */ +/* UX_EHCI_TD * Pointer to TD */ +/* */ +/* CALLS */ +/* */ +/* (ux_transfer_request_completion_function) Completion function */ +/* _ux_hcd_ehci_ed_clean Clean ED */ +/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_EHCI_TD *_ux_hcd_ehci_asynch_td_process(UX_EHCI_ED *ed, UX_EHCI_TD *td) +{ + +UX_TRANSFER *transfer_request; +ULONG td_residual_length; +UINT td_error; +UX_EHCI_TD *next_td; +ULONG td_element; +ULONG pid; + + + /* If the TD is still active, we know that the transfer has not taken place yet. In this case, + the TDs following this one do not need to be process and we return a NULL TD. */ + if (td -> ux_ehci_td_control & UX_EHCI_TD_ACTIVE) + return(UX_NULL); + + /* We need the transfer request associated with this TD. */ + transfer_request = td -> ux_ehci_td_transfer_request; + + /* We have a non active TD, meaning the TD was processed. We should explore the error code and + translate it into a generic USBX code. */ + td_error = UX_SUCCESS; + + /* Check if the TD was halted due to a major error. Note that the error status may contain an error + but unless the Halt bit is set, it is not fatal. */ + if (td -> ux_ehci_td_control & UX_EHCI_TD_HALTED) + { + + /* Default to STALL. */ + td_error = UX_TRANSFER_STALLED; + + /* What else could it be ? Buffer underrun/overrun ? */ + if (td -> ux_ehci_td_control & UX_EHCI_TD_DATA_BUFFER_ERROR) + td_error = UX_TRANSFER_ERROR; + + /* Babble ? */ + if (td -> ux_ehci_td_control & UX_EHCI_TD_BABBLE_DETECTED) + td_error = UX_TRANSFER_ERROR; + + /* Timeout, CRD, Bad PID ... ? */ + if (td -> ux_ehci_td_control & UX_EHCI_TD_TRANSACTION_ERROR) + td_error = UX_TRANSFER_NO_ANSWER; + + } + + /* If there is an error, we should terminate this transfer and clean things. */ + if (td_error != UX_SUCCESS) + { + + /* Update the transfer code. */ + transfer_request -> ux_transfer_request_completion_code = td_error; + + /* Clean the link. */ + _ux_hcd_ehci_ed_clean(ed); + + /* Free the TD that was just treated. */ + td -> ux_ehci_td_status = UX_UNUSED; + + /* We may do a call back. */ + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + + /* Notify the application for debugging purposes. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, td_error); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, td_error, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Wake up the semaphore for this request. */ + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + + /* Nothing else to be processed in this queue. */ + return(UX_NULL); + } + + /* Update the length of this transaction if the PID is IN or OUT. */ + pid = td -> ux_ehci_td_control & UX_EHCI_PID_MASK; + td_residual_length = 0; + if ((pid == UX_EHCI_PID_OUT) || (pid == UX_EHCI_PID_IN)) + { + + td_residual_length = (td -> ux_ehci_td_control >> UX_EHCI_TD_LG_LOC) & UX_EHCI_TD_LG_MASK; + transfer_request -> ux_transfer_request_actual_length += td -> ux_ehci_td_length - td_residual_length; + } + + /* We get here when there is no error on the transfer. It may be that this transfer is not the last + one in the link and therefore we process the length received but do not complete the transfer request. */ + if (td -> ux_ehci_td_control & UX_EHCI_TD_IOC) + { + + /* Check if this transaction is complete or a short packet occurred, in both case, complete the + transaction. In the case of a control endpoint in STATUS phase we complete regardless. */ + if ((td_residual_length != 0) || + (transfer_request -> ux_transfer_request_actual_length == transfer_request -> ux_transfer_request_requested_length) || + (td -> ux_ehci_td_phase & UX_EHCI_TD_STATUS_PHASE)) + { + + /* Update the transfer code. */ + transfer_request -> ux_transfer_request_completion_code = UX_SUCCESS; + + /* Clean the link. */ + _ux_hcd_ehci_ed_clean(ed); + + /* Free the TD that was just treated. */ + td -> ux_ehci_td_status = UX_UNUSED; + + /* We may do a call back. */ + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + + /* Wake up the semaphore for this request. */ + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + + /* Nothing else to be processed in this queue */ + return(UX_NULL); + } + } + + /* Get the next TD attached to this TD. */ + td_element = (ULONG) td -> ux_ehci_td_link_pointer; + td_element &= ~UX_EHCI_TD_T; + next_td = _ux_utility_virtual_address((VOID *) td_element); + + /* Free the TD that was just treated. */ + td -> ux_ehci_td_status = UX_UNUSED; + + /* This TD is now the first TD. */ + ed -> ux_ehci_ed_first_td = next_td; + + /* We get here when we have reached a non completion of a request transfer + we need to return the next TD in the linked list. */ + return(next_td); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_asynchronous_endpoint_create.c b/common/usbx_host_controllers/src/ux_hcd_ehci_asynchronous_endpoint_create.c new file mode 100644 index 0000000..f7e22d5 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_asynchronous_endpoint_create.c @@ -0,0 +1,172 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_asynchronous_endpoint_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will create an asynchronous endpoint. The control */ +/* and bulk endpoints fall into this category. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_ed_obtain Obtain EHCI ED */ +/* _ux_utility_physical_address Get physical address */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_asynchronous_endpoint_create(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint) +{ + +UX_DEVICE *device; +UX_EHCI_ED *ed; +UX_EHCI_LINK_POINTER queue_head; + + + /* We need to take into account the nature of the HCD to define the max size + of any transfer in the transfer request. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_maximum_length = UX_EHCI_MAX_PAYLOAD; + + /* Obtain a ED for this new endpoint. This ED will live as long as the endpoint is active + and will be the container for the tds. */ + ed = _ux_hcd_ehci_ed_obtain(hcd_ehci); + if (ed == UX_NULL) + return(UX_NO_ED_AVAILABLE); + + /* Attach the ED to the endpoint container. */ + endpoint -> ux_endpoint_ed = (VOID *) ed; + + /* Now do the opposite, attach the ED container to the physical ED. */ + ed -> ux_ehci_ed_endpoint = endpoint; + + /* Set the default MPS Capability info in the ED. */ + ed -> ux_ehci_ed_cap0 = endpoint -> ux_endpoint_descriptor.wMaxPacketSize << UX_EHCI_QH_MPS_LOC; + + /* Set the default NAK reload count. */ + ed -> ux_ehci_ed_cap0 |= UX_EHCI_QH_NCR; + + /* If the device is not high speed and the endpoint is control, then the CEF bit must be set to on. */ + device = endpoint -> ux_endpoint_device; + if ((device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) && + ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_CONTROL_ENDPOINT)) + ed -> ux_ehci_ed_cap0 |= UX_EHCI_QH_CEF; + + /* Set the device address. */ + ed -> ux_ehci_ed_cap0 |= device -> ux_device_address; + + /* Add the endpoint address. */ + ed -> ux_ehci_ed_cap0 |= (endpoint -> ux_endpoint_descriptor.bEndpointAddress & + ~UX_ENDPOINT_DIRECTION) << UX_EHCI_QH_ED_AD_LOC; + + /* Set the High Bandwidth Pipe Multiplier to 1. */ + ed -> ux_ehci_ed_cap1 |= UX_EHCI_QH_HBPM; + + /* Set the device speed for full and low speed devices behind a hub the hub address and the + port index must be stored in the endpoint. */ + switch (device -> ux_device_speed) + { + + case UX_HIGH_SPEED_DEVICE: + + ed -> ux_ehci_ed_cap0 |= UX_EHCI_QH_HIGH_SPEED; + break; + + + case UX_LOW_SPEED_DEVICE: + + ed -> ux_ehci_ed_cap0 |= UX_EHCI_QH_LOW_SPEED; + break; + + case UX_FULL_SPEED_DEVICE: + + /* The device must be on a hub for this code to execute. We still do a sanity check. */ + if (device -> ux_device_parent != UX_NULL) + { + + /* Store the parent hub device address. */ + ed -> ux_ehci_ed_cap1 |= device -> ux_device_parent -> ux_device_address << UX_EHCI_QH_HUB_ADDR_LOC; + + /* And the port index onto which this device is attached. */ + ed -> ux_ehci_ed_cap1 |= device -> ux_device_port_location << UX_EHCI_QH_PORT_NUMBER_LOC; + } + break; + } + + /* We need to insert this new endpoint into the asynchronous list. All new EDs are inserted at the + end of the list. The current ED will be pointing to the first ED in the list. */ + queue_head.void_ptr = _ux_utility_physical_address(hcd_ehci -> ux_hcd_ehci_asynch_first_list); + queue_head.value |= UX_EHCI_QH_TYP_QH; + ed -> ux_ehci_ed_queue_head = queue_head.ed_ptr; + ed -> ux_ehci_ed_next_ed = hcd_ehci -> ux_hcd_ehci_asynch_first_list; + + /* Now we compute the address and the data type to fill the QH pointer with. */ + queue_head.void_ptr = _ux_utility_physical_address(ed); + queue_head.value |= UX_EHCI_QH_TYP_QH; + hcd_ehci -> ux_hcd_ehci_asynch_last_list -> ux_ehci_ed_queue_head = queue_head.ed_ptr; + ed -> ux_ehci_ed_previous_ed = hcd_ehci -> ux_hcd_ehci_asynch_last_list; + + /* Update the link of the previous ED. */ + ed -> ux_ehci_ed_previous_ed -> ux_ehci_ed_next_ed = ed; + + /* Remember the new last QH. */ + hcd_ehci -> ux_hcd_ehci_asynch_last_list = ed; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_asynchronous_endpoint_destroy.c b/common/usbx_host_controllers/src/ux_hcd_ehci_asynchronous_endpoint_destroy.c new file mode 100644 index 0000000..308c71e --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_asynchronous_endpoint_destroy.c @@ -0,0 +1,115 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_asynchronous_endpoint_destroy PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will destroy an asynchronous endpoint. The control */ +/* and bulk endpoints fall into this category. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_door_bell_wait Wait for door bell */ +/* _ux_utility_physical_address Get physical address */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_asynchronous_endpoint_destroy(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint) +{ + +UX_EHCI_ED *ed; +UX_EHCI_ED *previous_ed; +UX_EHCI_ED *next_ed; +UX_EHCI_LINK_POINTER queue_head; + + + /* From the endpoint container fetch the EHCI ED descriptor. */ + ed = (UX_EHCI_ED *) endpoint -> ux_endpoint_ed; + + /* Get the previous ED in the list for this ED. */ + previous_ed = ed -> ux_ehci_ed_previous_ed; + + /* Get the next ED in the list for this ED. */ + next_ed = ed -> ux_ehci_ed_next_ed; + + /* Point the previous ED to the ED after the ED to be removed. */ + previous_ed -> ux_ehci_ed_next_ed = next_ed; + + /* Point the next ED previous pointer to the previous ED. */ + next_ed -> ux_ehci_ed_previous_ed = previous_ed; + + /* Now remove the physical link. */ + queue_head.void_ptr = _ux_utility_physical_address(next_ed); + queue_head.value |= UX_EHCI_QH_TYP_QH; + previous_ed -> ux_ehci_ed_queue_head = queue_head.ed_ptr; + + /* If this ED was the last ED, we need to update the HCD last ED value. */ + if (hcd_ehci -> ux_hcd_ehci_asynch_last_list == ed) + hcd_ehci -> ux_hcd_ehci_asynch_last_list = previous_ed; + + /* Arm the doorbell and wait for its completion. */ + _ux_hcd_ehci_door_bell_wait(hcd_ehci); + + /* Now we can safely make the ED free. */ + ed -> ux_ehci_ed_status = UX_UNUSED; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_controller_disable.c b/common/usbx_host_controllers/src/ux_hcd_ehci_controller_disable.c new file mode 100644 index 0000000..4d8e648 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_controller_disable.c @@ -0,0 +1,106 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_controller_disable PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will disable the EHCI controller. The controller will */ +/* release all its resources (memory, IO ...). After this, the */ +/* controller will not send SOF any longer. */ +/* */ +/* All transactions should have been completed, all classes should */ +/* have been closed. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_register_read Read EHCI register */ +/* _ux_hcd_ehci_register_write Write EHCI register */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_controller_disable(UX_HCD_EHCI *hcd_ehci) +{ + +UX_HCD *hcd; +ULONG ehci_register; + + + /* Point to the generic portion of the host controller structure instance. */ + hcd = hcd_ehci -> ux_hcd_ehci_hcd_owner; + + /* Stop the controller. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_USB_COMMAND); + ehci_register = EHCI_HC_IO_HCRESET; + ehci_register &= ~EHCI_HC_IO_RS; + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_USB_COMMAND, ehci_register); + + /* Wait for the Stop signal to be acknowledged by the controller. */ + ehci_register = 0; + while ((ehci_register&EHCI_HC_STS_HC_HALTED) == 0) + { + + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCCR_HCS_PARAMS); + } + + /* Reflect the state of the controller in the main structure. */ + hcd -> ux_hcd_status = UX_HCD_STATUS_HALTED; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_done_queue_process.c b/common/usbx_host_controllers/src/ux_hcd_ehci_done_queue_process.c new file mode 100644 index 0000000..722c3dc --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_done_queue_process.c @@ -0,0 +1,167 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_done_queue_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function process the isochronous, periodic and asynchronous */ +/* lists in search for transfers that occurred in the past */ +/* (micro-)frame. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_asynch_td_process Process asynch TD */ +/* _ux_hcd_ehci_hsisochronous_tds_process */ +/* Process high speed */ +/* isochronous TDs */ +/* _ux_hcd_ehci_fsisochronous_tds_process */ +/* Process full speed (split) */ +/* isochronous TDs */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ehci_done_queue_process(UX_HCD_EHCI *hcd_ehci) +{ + +UX_EHCI_TD *td; +UX_EHCI_PERIODIC_LINK_POINTER ed; +UX_EHCI_ED *start_ed; +UX_EHCI_PERIODIC_LINK_POINTER lp; + + +#if UX_MAX_ISO_TD + + /* We scan the active isochronous list first. */ + _ux_utility_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + lp.itd_ptr = hcd_ehci -> ux_hcd_ehci_hsiso_scan_list; + while(lp.itd_ptr != UX_NULL) + { + + /* Process the iTD, return next active TD. */ + lp.itd_ptr = _ux_hcd_ehci_hsisochronous_tds_process(hcd_ehci, lp.itd_ptr); + } + _ux_utility_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + + /* We scan the split isochronous list then. */ + _ux_utility_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + lp.sitd_ptr = hcd_ehci -> ux_hcd_ehci_fsiso_scan_list; + while(lp.sitd_ptr != UX_NULL) + { + + /* Process the iTD, return next active TD. */ + lp.sitd_ptr = _ux_hcd_ehci_fsisochronous_tds_process(hcd_ehci, lp.sitd_ptr); + } + _ux_utility_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + +#endif +#endif + + /* We scan the linked interrupt list then. */ + _ux_utility_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + ed.ed_ptr = hcd_ehci -> ux_hcd_ehci_interrupt_ed_list; + while(ed.ed_ptr != UX_NULL) + { + + /* Retrieve the fist TD attached to this ED. */ + td = ed.ed_ptr -> ux_ehci_ed_first_td; + + /* Process TD until there is no next available. */ + while (td != UX_NULL) + td = _ux_hcd_ehci_asynch_td_process(ed.ed_ptr, td); + + /* Next ED. */ + ed.ed_ptr = ed.ed_ptr -> ux_ehci_ed_next_ed; + } + _ux_utility_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + + /* Now we can parse the asynchronous list. The head ED is always empty and + used as an anchor only. */ + start_ed = hcd_ehci -> ux_hcd_ehci_asynch_head_list; + + /* Point to the next ED in the asynchronous tree. */ + ed.ed_ptr = start_ed -> ux_ehci_ed_queue_head; + ed.value &= UX_EHCI_LINK_ADDRESS_MASK; + + /* Obtain the virtual address from the element. */ + ed.void_ptr = _ux_utility_virtual_address(ed.void_ptr); + + /* Now traverse this list until we have found a non anchor endpoint that + has transfers done. */ + while (ed.ed_ptr != start_ed) + { + + /* Retrieve the fist TD attached to this ED. */ + td = ed.ed_ptr -> ux_ehci_ed_first_td; + while (td != UX_NULL) + { + + td = _ux_hcd_ehci_asynch_td_process(ed.ed_ptr, td); + } + + /* Point to the next ED in the asynchronous tree. */ + ed.ed_ptr = ed.ed_ptr -> ux_ehci_ed_queue_head; + ed.value &= UX_EHCI_LINK_ADDRESS_MASK; + + /* Obtain the virtual address from the element. */ + ed.void_ptr = _ux_utility_virtual_address(ed.void_ptr); + } +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_door_bell_wait.c b/common/usbx_host_controllers/src/ux_hcd_ehci_door_bell_wait.c new file mode 100644 index 0000000..39f8b87 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_door_bell_wait.c @@ -0,0 +1,101 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_door_bell_wait PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will raise the doorbell and wait for its */ +/* acknowledgement. This mechanism is used to safely remove a physical */ +/* endpoint from EHCI. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_register_read Read EHCI register */ +/* _ux_hcd_ehci_register_write Write EHCI register */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_semaphore_put Release semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ehci_door_bell_wait(UX_HCD_EHCI *hcd_ehci) +{ + +ULONG ehci_register; +UINT status; + + + /* Protect against multiple thread entry to this HCD. */ + status = _ux_utility_semaphore_get(&hcd_ehci -> ux_hcd_ehci_protect_semaphore, UX_WAIT_FOREVER); + if (status != UX_SUCCESS) + return; + + /* Raise the doorbell to the HCD. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_USB_COMMAND); + ehci_register |= EHCI_HC_IO_IAAD; + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_USB_COMMAND, ehci_register); + + /* Wait for the doorbell to be awaken. */ + status = _ux_utility_semaphore_get(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore, UX_WAIT_FOREVER); + + /* Free the protection semaphore. */ + status = _ux_utility_semaphore_put(&hcd_ehci -> ux_hcd_ehci_protect_semaphore); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_ed_clean.c b/common/usbx_host_controllers/src/ux_hcd_ehci_ed_clean.c new file mode 100644 index 0000000..a60653a --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_ed_clean.c @@ -0,0 +1,110 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_ed_clean PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cleans the tds attached to a ED in case a transfer */ +/* has to be aborted. */ +/* */ +/* INPUT */ +/* */ +/* ed Pointer to ED */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_ed_clean(UX_EHCI_ED *ed) +{ + +UX_EHCI_TD *td; +UX_EHCI_TD *next_td; + + + /* Get the first pointer to the TD. */ + td = ed -> ux_ehci_ed_queue_element; + td = (UX_EHCI_TD *) ((ULONG) td & ~UX_EHCI_QH_T); + td = _ux_utility_virtual_address(td); + + /* Mark the TD link of the endpoint as terminated. */ + ed -> ux_ehci_ed_queue_element = (UX_EHCI_TD *) UX_EHCI_TD_T; + + /* Free all tds attached to the ED. */ + while (td != UX_NULL) + { + + /* Get the next TD pointed by the current TD. */ + next_td = td -> ux_ehci_td_link_pointer; + next_td = (UX_EHCI_TD *) ((ULONG) next_td & ~UX_EHCI_TD_T); + next_td = _ux_utility_virtual_address(next_td); + + /* Mark the current TD as free. */ + td -> ux_ehci_td_status = UX_UNUSED; + + td = next_td; + } + + /* Reset the first TD. */ + ed -> ux_ehci_ed_first_td = UX_NULL; + + /* Reset the last TD. */ + ed -> ux_ehci_ed_last_td = UX_NULL; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_ed_obtain.c b/common/usbx_host_controllers/src/ux_hcd_ehci_ed_obtain.c new file mode 100644 index 0000000..85d72fb --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_ed_obtain.c @@ -0,0 +1,107 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_ed_obtain PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains a free ED from the ED list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* UX_EHCI_ED * Pointer to ED */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_set Set memory block */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_EHCI_ED *_ux_hcd_ehci_ed_obtain(UX_HCD_EHCI *hcd_ehci) +{ + +UX_EHCI_ED *ed; +ULONG ed_index; + + + /* Start the search from the beginning of the list. */ + ed = hcd_ehci -> ux_hcd_ehci_ed_list; + for (ed_index = 0; ed_index < _ux_system_host -> ux_system_host_max_ed; ed_index++) + { + + /* Check the ED status, a free ED is marked with the UNUSED flag. */ + if (ed -> ux_ehci_ed_status == UX_UNUSED) + { + + /* The ED may have been used, so we reset all fields. */ + _ux_utility_memory_set(ed, 0, sizeof(UX_EHCI_ED)); + + /* This ED is now marked as USED. */ + ed -> ux_ehci_ed_status = UX_USED; + + /* We initialize the type of ED and mark its TD terminator to be safe. */ + ed -> ux_ehci_ed_queue_head = (UX_EHCI_ED *) UX_EHCI_QH_TYP_QH; + ed -> ux_ehci_ed_queue_element = (UX_EHCI_TD *) UX_EHCI_TD_T; + + /* Success, return ED pointer. */ + return(ed); + } + + /* Point to the next ED. */ + ed++; + } + + /* There is no available ED in the ED list. */ + return(UX_NULL); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_endpoint_reset.c b/common/usbx_host_controllers/src/ux_hcd_ehci_endpoint_reset.c new file mode 100644 index 0000000..b69aaf9 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_endpoint_reset.c @@ -0,0 +1,91 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_endpoint_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will reset an endpoint. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_endpoint_reset(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint) +{ + +UX_EHCI_ED *ed; +ULONG ed_value; + + + UX_PARAMETER_NOT_USED(hcd_ehci); + + /* From the endpoint container fetch the EHCI ED descriptor. */ + ed = (UX_EHCI_ED*) endpoint -> ux_endpoint_ed; + + /* Reset the data0/data1 toggle bit in the Overlay portion of the ED. */ + ed_value = ed -> ux_ehci_ed_state; + ed_value &= ~UX_EHCI_QH_TOGGLE; + ed -> ux_ehci_ed_state = ed_value; + + /* This operation never fails! */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_entry.c b/common/usbx_host_controllers/src/ux_hcd_ehci_entry.c new file mode 100644 index 0000000..a9e2bf4 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_entry.c @@ -0,0 +1,268 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function dispatch the HCD function internally to the EHCI */ +/* controller. */ +/* */ +/* INPUT */ +/* */ +/* HCD Pointer to HCD */ +/* function Requested function */ +/* parameter Pointer to parameter(s) */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_asynchronous_endpoint_create Create endpoint */ +/* _ux_hcd_ehci_asynchronous_endpoint_destroy Destroy endpoint */ +/* _ux_hcd_ehci_controller_disable Disable controller */ +/* _ux_hcd_ehci_done_queue_process Process done queue */ +/* _ux_hcd_ehci_endpoint_reset Reset endpoint */ +/* _ux_hcd_ehci_frame_number_get Get frame number */ +/* _ux_hcd_ehci_frame_number_set Set frame number */ +/* _ux_hcd_ehci_interrupt_endpoint_create Endpoint create */ +/* _ux_hcd_ehci_interrupt_endpoint_destroy Endpoint destroy */ +/* _ux_hcd_ehci_isochronous_endpoint_create Endpoint create */ +/* _ux_hcd_ehci_isochronous_endpoint_destroy Endpoint destroy */ +/* _ux_hcd_ehci_port_disable Disable port */ +/* _ux_hcd_ehci_port_reset Reset port */ +/* _ux_hcd_ehci_port_resume Resume port */ +/* _ux_hcd_ehci_port_status_get Get port status */ +/* _ux_hcd_ehci_port_suspend Suspend port */ +/* _ux_hcd_ehci_power_down_port Power down port */ +/* _ux_hcd_ehci_power_on_port Power on port */ +/* _ux_hcd_ehci_request_transfer Request transfer */ +/* _ux_hcd_ehci_transfer_abort Abort transfer */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_entry(UX_HCD *hcd, UINT function, VOID *parameter) +{ + +UINT status; +UX_HCD_EHCI *hcd_ehci; + + + /* Check the status of the controller. */ + if (hcd -> ux_hcd_status == UX_UNUSED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_CONTROLLER_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONTROLLER_UNKNOWN, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONTROLLER_UNKNOWN); + } + + /* Get the pointer to the EHCI HCD. */ + hcd_ehci = (UX_HCD_EHCI *) hcd -> ux_hcd_controller_hardware; + + /* Look at the function and route it. */ + switch(function) + { + + case UX_HCD_DISABLE_CONTROLLER: + + status = _ux_hcd_ehci_controller_disable(hcd_ehci); + break; + + + case UX_HCD_GET_PORT_STATUS: + status = _ux_hcd_ehci_port_status_get(hcd_ehci, (ULONG) parameter); + break; + + + case UX_HCD_ENABLE_PORT: + + status = UX_SUCCESS; + break; + + + case UX_HCD_DISABLE_PORT: + + status = _ux_hcd_ehci_port_disable(hcd_ehci, (ULONG) parameter); + break; + + + case UX_HCD_POWER_ON_PORT: + + status = _ux_hcd_ehci_power_on_port(hcd_ehci, (ULONG) parameter); + break; + + + case UX_HCD_POWER_DOWN_PORT: + + status = _ux_hcd_ehci_power_down_port(hcd_ehci, (ULONG) parameter); + break; + + + case UX_HCD_SUSPEND_PORT: + status = _ux_hcd_ehci_port_suspend(hcd_ehci, (ULONG) parameter); + break; + + + case UX_HCD_RESUME_PORT: + + status = _ux_hcd_ehci_port_resume(hcd_ehci, (UINT) parameter); + break; + + + case UX_HCD_RESET_PORT: + + status = _ux_hcd_ehci_port_reset(hcd_ehci, (ULONG) parameter); + break; + + + case UX_HCD_GET_FRAME_NUMBER: + + status = _ux_hcd_ehci_frame_number_get(hcd_ehci, (ULONG *) parameter); + break; + + + case UX_HCD_SET_FRAME_NUMBER: + + _ux_hcd_ehci_frame_number_set(hcd_ehci, (ULONG) parameter); + status = UX_SUCCESS; + break; + + + case UX_HCD_TRANSFER_REQUEST: + + status = _ux_hcd_ehci_request_transfer(hcd_ehci, (UX_TRANSFER *) parameter); + break; + + + case UX_HCD_TRANSFER_ABORT: + + status = _ux_hcd_ehci_transfer_abort(hcd_ehci, (UX_TRANSFER *) parameter); + break; + + + case UX_HCD_CREATE_ENDPOINT: + + switch ((((UX_ENDPOINT*) parameter) -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + case UX_BULK_ENDPOINT: + status = _ux_hcd_ehci_asynchronous_endpoint_create(hcd_ehci, (UX_ENDPOINT*) parameter); + break; + + case UX_INTERRUPT_ENDPOINT: + status = _ux_hcd_ehci_interrupt_endpoint_create(hcd_ehci, (UX_ENDPOINT*) parameter); + break; + + case UX_ISOCHRONOUS_ENDPOINT: + status = _ux_hcd_ehci_isochronous_endpoint_create(hcd_ehci, (UX_ENDPOINT*) parameter); + break; + + } + break; + + + case UX_HCD_DESTROY_ENDPOINT: + + switch ((((UX_ENDPOINT*) parameter) -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + case UX_BULK_ENDPOINT: + status = _ux_hcd_ehci_asynchronous_endpoint_destroy(hcd_ehci, (UX_ENDPOINT*) parameter); + break; + + case UX_INTERRUPT_ENDPOINT: + status = _ux_hcd_ehci_interrupt_endpoint_destroy(hcd_ehci, (UX_ENDPOINT*) parameter); + break; + + case UX_ISOCHRONOUS_ENDPOINT: + status = _ux_hcd_ehci_isochronous_endpoint_destroy(hcd_ehci, (UX_ENDPOINT*) parameter); + break; + + } + break; + + + case UX_HCD_RESET_ENDPOINT: + + status = _ux_hcd_ehci_endpoint_reset(hcd_ehci, (UX_ENDPOINT*) parameter); + break; + + + case UX_HCD_PROCESS_DONE_QUEUE: + + _ux_hcd_ehci_done_queue_process(hcd_ehci); + status = UX_SUCCESS; + break; + + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + status = UX_FUNCTION_NOT_SUPPORTED; + break; + } + + /* Return status to caller. */ + return(status); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_frame_number_get.c b/common/usbx_host_controllers/src/ux_hcd_ehci_frame_number_get.c new file mode 100644 index 0000000..a284f77 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_frame_number_get.c @@ -0,0 +1,88 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_frame_number_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will return the frame number currently used by the */ +/* controller. This function is mostly used for isochronous purposes. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* frame_number Pointer to frame number */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_register_read Read EHCI register */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_frame_number_get(UX_HCD_EHCI *hcd_ehci, ULONG *frame_number) +{ + +ULONG ehci_register; + + + /* Read the micro frame number register. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_FRAME_INDEX); + + /* The register is based on micro frames, so we need to divide the + value by 8 to get to the millisecond frame number. */ + *frame_number = (ehci_register >> 3) & 0x3ff; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_frame_number_set.c b/common/usbx_host_controllers/src/ux_hcd_ehci_frame_number_set.c new file mode 100644 index 0000000..a80b5ad --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_frame_number_set.c @@ -0,0 +1,95 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_frame_number_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will set the current frame number to the one */ +/* specified. This function is mostly used for isochronous purposes. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* frame_number Frame number */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_register_read Read EHCI register */ +/* _ux_hcd_ehci_register_write Write EHCI register */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ehci_frame_number_set(UX_HCD_EHCI *hcd_ehci, ULONG frame_number) +{ + +ULONG ehci_register; + + + /* It is illegal in EHCI to set the frame number while the controller is + running. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_USB_COMMAND); + if (ehci_register & EHCI_HC_IO_RS) + return; + + /* The register is based on micro frames, so we need to multiply the + value by 8 to get to the millisecond frame number. */ + ehci_register = frame_number << 3; + + /* Write the frame number, by default the micro frame will be set to 0. */ + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_FRAME_INDEX, ehci_register); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_fsisochronous_td_obtain.c b/common/usbx_host_controllers/src/ux_hcd_ehci_fsisochronous_td_obtain.c new file mode 100644 index 0000000..0bc0ce3 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_fsisochronous_td_obtain.c @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_fsisochronous_td_obtain PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains a free TD from the full speed isochronous */ +/* TD list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* UX_EHCI_FSISO_TD * Pointer to EHCI FSISO TD */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_EHCI_FSISO_TD *_ux_hcd_ehci_fsisochronous_td_obtain(UX_HCD_EHCI *hcd_ehci) +{ +#if UX_MAX_ISO_TD == 0 || !defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + + /* This function is not yet supported, return NULL. */ + UX_PARAMETER_NOT_USED(hcd_ehci); + return(UX_NULL); +#else + +UX_EHCI_FSISO_TD *td; +ULONG td_index; + + + /* Start the search from the beginning of the list. */ + td = hcd_ehci -> ux_hcd_ehci_fsiso_td_list; + for (td_index = 0; td_index < _ux_system_host -> ux_system_host_max_iso_td; td_index++) + { + + /* Check the TD status, a free TD is marked with the USED flag. */ + if (td -> ux_ehci_fsiso_td_status == UX_UNUSED) + { + + /* The TD may have been used, so we reset all fields. */ + _ux_utility_memory_set(td, 0, sizeof(UX_EHCI_FSISO_TD)); + + /* This TD is now marked as USED. */ + td -> ux_ehci_fsiso_td_status = UX_USED; + + /* Initialize the link pointer TD fields. */ + td -> ux_ehci_fsiso_td_next_lp.value = UX_EHCI_FSISO_T; + + /* Success, return TD pointer. */ + return(td); + } + + /* Look at next TD. */ + td++; + } + + /* There is no available TD in the TD list. */ + + /* Error, return a null. */ + return(UX_NULL); +#endif +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_fsisochronous_tds_process.c b/common/usbx_host_controllers/src/ux_hcd_ehci_fsisochronous_tds_process.c new file mode 100644 index 0000000..463a985 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_fsisochronous_tds_process.c @@ -0,0 +1,88 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_fsisochronous_tds_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the isochronous, periodic and asynchronous */ +/* lists in search for transfers that occurred in the past */ +/* (micro-)frame. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to HCD EHCI */ +/* prev_itd Pointer to pointer point to */ +/* previous FSISO TD */ +/* itd Pointer to FSISO TD */ +/* */ +/* OUTPUT */ +/* */ +/* UX_EHCI_HSISO_TD Pointer to FSISO TD */ +/* */ +/* CALLS */ +/* */ +/* (ux_transfer_request_completion_function) Completion function */ +/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_utility_physical_address Get physical address */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_EHCI_FSISO_TD* _ux_hcd_ehci_fsisochronous_tds_process( + UX_HCD_EHCI *hcd_ehci, + UX_EHCI_FSISO_TD* itd) +{ + + UX_PARAMETER_NOT_USED(hcd_ehci); + + /* TBD */ + + return(itd -> ux_ehci_fsiso_td_next_scan_td); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_hsisochronous_td_obtain.c b/common/usbx_host_controllers/src/ux_hcd_ehci_hsisochronous_td_obtain.c new file mode 100644 index 0000000..be4d295 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_hsisochronous_td_obtain.c @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_hsisochronous_td_obtain PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains a free TD from the high speed isochronous */ +/* TD list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* UX_EHCI_HSISO_TD * Pointer to EHCI HSISO TD */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_EHCI_HSISO_TD *_ux_hcd_ehci_hsisochronous_td_obtain(UX_HCD_EHCI *hcd_ehci) +{ +#if UX_MAX_ISO_TD == 0 + + /* This function is not yet supported, return NULL. */ + UX_PARAMETER_NOT_USED(hcd_ehci); + return(UX_NULL); +#else + +UX_EHCI_HSISO_TD *td; +ULONG td_index; + + + /* Start the search from the beginning of the list. */ + td = hcd_ehci -> ux_hcd_ehci_hsiso_td_list; + for (td_index = 0; td_index < _ux_system_host -> ux_system_host_max_iso_td; td_index++) + { + + /* Check the TD status, a free TD is marked with the USED flag. */ + if (td -> ux_ehci_hsiso_td_status == UX_UNUSED) + { + + /* The TD may have been used, so we reset all fields. */ + _ux_utility_memory_set(td, 0, sizeof(UX_EHCI_HSISO_TD)); + + /* This TD is now marked as USED. */ + td -> ux_ehci_hsiso_td_status = UX_USED; + + /* Initialize the link pointer TD fields. */ + td -> ux_ehci_hsiso_td_next_lp.value = UX_EHCI_HSISO_T; + + /* Success, return TD pointer. */ + return(td); + } + + /* Look at next TD. */ + td++; + } + + /* There is no available TD in the TD list. */ + + /* Error, return a null. */ + return(UX_NULL); +#endif +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_hsisochronous_tds_process.c b/common/usbx_host_controllers/src/ux_hcd_ehci_hsisochronous_tds_process.c new file mode 100644 index 0000000..b20af0d --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_hsisochronous_tds_process.c @@ -0,0 +1,443 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_hsisochronous_tds_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the iTDs of an isochronous endpoint. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to HCD EHCI */ +/* itd Pointer to HSISO TD */ +/* */ +/* OUTPUT */ +/* */ +/* UX_EHCI_HSISO_TD Pointer to HSISO TD */ +/* */ +/* CALLS */ +/* */ +/* (ux_transfer_request_completion_function) */ +/* Transfer Completion function */ +/* _ux_hcd_ehci_register_read Read EHCI register */ +/* _ux_utility_semaphore_put Put semaphore */ +/* _ux_utility_physical_address Get physical address */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_EHCI_HSISO_TD* _ux_hcd_ehci_hsisochronous_tds_process( + UX_HCD_EHCI *hcd_ehci, + UX_EHCI_HSISO_TD* itd) +{ + +UX_EHCI_HSISO_ED *ed; +UX_EHCI_HSISO_TD *next_scan_td; +ULONG n_fr; +ULONG frindex; +ULONG frindex1; +UX_EHCI_HSISO_TD *fr_td; +UX_EHCI_HSISO_TD *fr_td1; +ULONG control; +ULONG control1; +ULONG trans_bytes; +UX_TRANSFER *transfer; +UX_EHCI_POINTER bp; +ULONG pg; +ULONG pg_addr; +ULONG pg_offset; +ULONG frindex_now; +ULONG frindex_start; +USHORT fr_hc; +USHORT fr_sw; +UINT i; + + + /* Get ED. */ + ed = itd -> ux_ehci_hsiso_td_ed; + + /* Get next scan TD. */ + next_scan_td = itd -> ux_ehci_hsiso_td_next_scan_td; + + /* Check if iTD is skipped. */ + if (ed -> ux_ehci_hsiso_ed_frstart == 0xFF) + return(next_scan_td); + + /* + ** 1. There is requests loaded + ** (0) Micro-frame is active (request loaded) + ** (1) Active is cleared (HC processed) + ** (2) Handle it + ** 2. There is micro-frame free + ** (0) Micro-frame is free + ** (1) Micro-frame not overlap current FRINDEX + ** (2) Link request + ** (3) Build controls to active micro-frame + */ + + /* Get number of frames (8,4,2 or 1). */ + n_fr = 8 >> ed -> ux_ehci_hsiso_ed_frinterval_shift; + + /* Process if there is requests loaded. */ + if (ed -> ux_ehci_hsiso_ed_frload > 0) + { + + /* Process count to target micro frames. */ + fr_hc = ed -> ux_ehci_hsiso_ed_fr_hc << ed -> ux_ehci_hsiso_ed_frinterval_shift; + fr_hc += ed -> ux_ehci_hsiso_ed_frstart; + fr_hc &= 0x7u; + + /* Process done iTDs. */ + for (i = 0; + i < n_fr; /* 8, 4, 2 or 1. */ + i += ed -> ux_ehci_hsiso_ed_frinterval) + { + + /* Get frindex. */ + frindex = fr_hc + i; + frindex &= 7u; + + if ((ed -> ux_ehci_hsiso_ed_frload & (1u << frindex)) == 0) + { + break; + } + + /* Get iTD for the micro-frame. */ + fr_td = ed -> ux_ehci_hsiso_ed_fr_td[frindex >> 1]; + + /* Get control. */ + control = fr_td -> ux_ehci_hsiso_td_control[frindex]; + + /* Check next frame state, if multiple micro-frames loaded. */ + if (n_fr > 1) + { + + /* Micro-frame is active, check next. */ + if (control & UX_EHCI_HSISO_STATUS_ACTIVE) + { + + /* Get next frindex. */ + frindex1 = frindex + ed -> ux_ehci_hsiso_ed_frinterval; + frindex1 &= 7u; + + /* Get next iTD for the micro-frame. */ + fr_td1 = ed -> ux_ehci_hsiso_ed_fr_td[frindex1 >> 1]; + + /* Get control. */ + control1 = fr_td1 -> ux_ehci_hsiso_td_control[frindex1]; + + /* Next micro-frame is also active, break. */ + if (control1 & UX_EHCI_HSISO_STATUS_ACTIVE) + { + break; + } + else + { + + /* Next micro-frame is not loaded, break. */ + if ((ed -> ux_ehci_hsiso_ed_frload & (1u << frindex1)) == 0) + { + break; + } + + /* We are here when micro-frame 1 handled before micro-frame 0, + ** which means we missed one request. + */ + + /* Disable control, discard buffer and handle request. */ + control &= ~(UX_EHCI_HSISO_STATUS_ACTIVE | + UX_EHCI_HSISO_XACT_LENGTH_MASK); + fr_td -> ux_ehci_hsiso_td_control[frindex] = control; + } + + } /* if (control & UX_EHCI_HSISO_STATUS_ACTIVE) */ + } + else + { + + /* If iTD is active, break. */ + if (control & UX_EHCI_HSISO_STATUS_ACTIVE) + { + break; + } + } + + /* Clear load map anyway. */ + fr_td -> ux_ehci_hsiso_td_frload &= ~(1u << frindex); + ed -> ux_ehci_hsiso_ed_frload &= ~(1u << frindex); + + /* Handle the request. */ + transfer = ed -> ux_ehci_hsiso_ed_transfer_head; + + /* Convert error code to completion code. */ + if (control & UX_EHCI_HSISO_STATUS_DATA_BUFFER_ERR) + transfer -> ux_transfer_request_completion_code = UX_TRANSFER_BUFFER_OVERFLOW; + else + { + if (control & UX_EHCI_HSISO_STATUS_MASK) + transfer -> ux_transfer_request_completion_code = UX_TRANSFER_ERROR; + else + transfer -> ux_transfer_request_completion_code = UX_SUCCESS; + } + + /* Get transfer bytes. */ + trans_bytes = control & UX_EHCI_HSISO_XACT_LENGTH_MASK; + trans_bytes >>= UX_EHCI_HSISO_XACT_LENGTH_SHIFT; + + /* Save to actual length. */ + transfer -> ux_transfer_request_actual_length = trans_bytes; + + /* HC processed. */ + ed -> ux_ehci_hsiso_ed_fr_hc ++; + + /* Unlink it from iTD. */ + fr_td -> ux_ehci_hsiso_td_fr_transfer[frindex & 1u] = UX_NULL; + + /* Unlink it from request list head. */ + ed -> ux_ehci_hsiso_ed_transfer_head = + transfer -> ux_transfer_request_next_transfer_request; + + /* If no more requests, also set tail to NULL. */ + if (ed -> ux_ehci_hsiso_ed_transfer_head == UX_NULL) + ed -> ux_ehci_hsiso_ed_transfer_tail = UX_NULL; + + /* Invoke callback. */ + if (transfer -> ux_transfer_request_completion_function) + transfer -> ux_transfer_request_completion_function(transfer); + + /* Put semaphore. */ + _ux_utility_semaphore_put(&transfer -> ux_transfer_request_semaphore); + + } /* for (;i < n_fr;) */ + } + + /* Build request when there is new unloaded requests. */ + if (ed -> ux_ehci_hsiso_ed_transfer_first_new) + { + + /* Get current FRINDEX for SW process. */ + frindex_now = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_FRAME_INDEX); + frindex_now &= 0x7u; + + /* If transfer starts. */ + if (ed -> ux_ehci_hsiso_ed_frstart == 0xFE) + { + + /* 1 micro-frame in iTD. */ + if (ed -> ux_ehci_hsiso_ed_frinterval_shift >= 3) + { + + /* Uses this only micro-frame index. */ + ed -> ux_ehci_hsiso_ed_frstart = ed -> ux_ehci_hsiso_ed_frindex; + } + + /* 8,4,2 micro-frames in each iTD. */ + else + { + + /* Get start index for sw to link requests. */ + if (ed -> ux_ehci_hsiso_ed_frinterval_shift == 0) + + /* Interval 1, just add two. */ + frindex_start = frindex_now + 2; + else + { + + /* Interval 2, 4. */ + /* Scan indexes, to find an index that has 2 in front or more. */ + for (frindex_start = ed -> ux_ehci_hsiso_ed_frindex; + frindex_start < 9; + frindex_start += ed -> ux_ehci_hsiso_ed_frinterval) + { + if (frindex_start - frindex_now >= 2) + break; + } + } + + /* Target to start index calculated and wrap around in one frame. */ + ed -> ux_ehci_hsiso_ed_frstart = frindex_start & 7u; + } + } /* if (ed -> ux_ehci_hsiso_ed_fr_sw == 0xFE) */ + + /* Process count to target micro frames. */ + fr_sw = ed -> ux_ehci_hsiso_ed_fr_sw << ed -> ux_ehci_hsiso_ed_frinterval_shift; + fr_sw += ed -> ux_ehci_hsiso_ed_frstart; + fr_sw &= 0x7u; + + /* Build requests. */ + for (i = 0; + i < n_fr; + i += ed -> ux_ehci_hsiso_ed_frinterval) + { + + /* Get micro-frame index. */ + frindex = i + fr_sw; + frindex &= 7u; + + /* Get iTD. */ + fr_td = ed -> ux_ehci_hsiso_ed_fr_td[frindex >> 1]; + + /* Check load status. */ + if (fr_td -> ux_ehci_hsiso_td_frload & (1u << frindex)) + { + break; + } + + /* Get a transfer request. */ + transfer = ed -> ux_ehci_hsiso_ed_transfer_first_new; + if (transfer == UX_NULL) + { + break; + } + + /* Get control status. */ + control = fr_td -> ux_ehci_hsiso_td_control[frindex]; + + /* If there are multiple micro-frames, check + ** (1) If target micro-frame is already loaded + ** (2) If the micro-frame overlapped current one + */ + if (n_fr) + { + + /* If already loaded(active), break. */ + if (control & UX_EHCI_HSISO_STATUS_ACTIVE) + { + break; + } + + /* If index overlap, break. */ + + /* Check if frindex exceeds same FRINDEX in next frame. */ + if ((frindex == frindex_now) || (i + fr_sw >= frindex_now + 8)) + { + break; + } + } + + /* Now new request is linking. */ + + /* Process count inc. */ + ed -> ux_ehci_hsiso_ed_fr_sw ++; + + /* Sanity check, iTD is not linked. */ + while(fr_td -> ux_ehci_hsiso_td_fr_transfer[frindex & 1u] != UX_NULL); + + /* Link it to iTD. */ + fr_td -> ux_ehci_hsiso_td_fr_transfer[frindex & 1u] = transfer; + + /* Remove it from new free list. */ + ed -> ux_ehci_hsiso_ed_transfer_first_new = + transfer -> ux_transfer_request_next_transfer_request; + + /* Update load map. */ + fr_td -> ux_ehci_hsiso_td_frload |= (1u << frindex); + ed -> ux_ehci_hsiso_ed_frload |= (1u << frindex); + + /* Get transfer size. */ + trans_bytes = transfer -> ux_transfer_request_requested_length; + + /* Limit max transfer size. */ + if (trans_bytes > fr_td -> ux_ehci_hsiso_td_max_trans_size) + trans_bytes = fr_td -> ux_ehci_hsiso_td_max_trans_size; + + /* Build the control. */ + + /* Keep IOC and PG. */ + control &= UX_EHCI_HSISO_IOC | UX_EHCI_HSISO_PG_MASK; + + /* New transfer size. */ + control |= (trans_bytes << UX_EHCI_HSISO_XACT_LENGTH_SHIFT); + + /* Active. */ + control |= (UX_EHCI_HSISO_STATUS_ACTIVE); + + /* Build offset & BPs (5,6/3,4). */ + + /* Get physical buffer address. */ + bp.void_ptr = _ux_utility_physical_address(transfer -> ux_transfer_request_data_pointer); + + /* Get page offset. */ + pg_addr = bp.value & UX_EHCI_PAGE_ALIGN; + pg_offset = bp.value & UX_EHCI_HSISO_XACT_OFFSET_MASK; + + /* Offset in control. */ + control |= pg_offset; + + /* Save BPs. */ + pg = (frindex & 1u) ? 5 : 3; + + /* PG in control. */ + control |= pg << UX_EHCI_HSISO_PG_SHIFT; + + /* Save BPs. */ + + /* First BP. */ + bp.value = pg_addr; + fr_td -> ux_ehci_hsiso_td_bp[pg] = bp.void_ptr; + + /* Next page information. */ + pg ++; + pg_addr += UX_EHCI_PAGE_SIZE; + + /* Next BP. */ + bp.value = pg_addr; + fr_td -> ux_ehci_hsiso_td_bp[pg] = bp.void_ptr; + + /* Save control. */ + UX_DATA_MEMORY_BARRIER + fr_td -> ux_ehci_hsiso_td_control[frindex] = control; + + } /* for(i = 0; i < n_fr; ) */ + + } /* if (ed -> ux_ehci_hsiso_ed_transfer_first_new) */ + + /* Return next iTD in scan list. */ + return(next_scan_td); +} diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_initialize.c b/common/usbx_host_controllers/src/ux_hcd_ehci_initialize.c new file mode 100644 index 0000000..49a1a6f --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_initialize.c @@ -0,0 +1,416 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/* EHCI HCD extention for host mode select. */ +#ifndef UX_HCD_EHCI_EXT_USB_HOST_MODE_ENABLE + +#if defined(K66) || defined(IMX6UL) || defined(XILINX_ZYNQ) || defined(MIMXRT) +#define UX_HCD_EHCI_EXT_USB_HOST_MODE_ENABLE(hcd_ehci) do \ +{ \ + _ux_hcd_ehci_register_write(hcd_ehci, (hcd_ehci -> ux_hcd_ehci_hcor + 0x1A), 0x03); \ +} while(0) +#else +#define UX_HCD_EHCI_EXT_USB_HOST_MODE_ENABLE(hcd_ehci) +#endif + +#endif /* ifndef UX_HCD_EHCI_EXT_USB_HOST_MODE_ENABLE */ + +#ifndef UX_HCD_EHCI_EXT_EMBEDDED_TT_SUPPORT + +#if defined(IMX25) || defined(IMX6UL) || defined(K66) || defined(LPC3131) || \ + defined(MCF5445X) || defined(MIMXRT) +#define UX_HCD_EHCI_EXT_EMBEDDED_TT_SUPPORT UX_TRUE +#else +#define UX_HCD_EHCI_EXT_EMBEDDED_TT_SUPPORT UX_FALSE +#endif + +#endif /* ifndef UX_HCD_EHCI_EXT_EMBEDDED_TT_SUPPORT */ + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the EHCI controller. It sets the DMA */ +/* areas, programs all the EHCI registers, sets up the ED and TD */ +/* containers, sets the control, bulk and periodic lists. */ +/* */ +/* INPUT */ +/* */ +/* HCD Pointer to HCD */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_periodic_tree_create Create periodic tree */ +/* _ux_hcd_ehci_power_root_hubs Power root HUBs */ +/* _ux_hcd_ehci_register_read Read EHCI register */ +/* _ux_hcd_ehci_register_write Write EHCI register */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_delete Delete memory block */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_semaphore_create Create semaphore */ +/* _ux_utility_semaphore_delete Delete semaphore */ +/* _ux_utility_mutex_create Create mutex */ +/* _ux_utility_mutex_delete Delete mutex */ +/* _ux_utility_set_interrupt_handler Set interrupt handler */ +/* _ux_utility_delay_ms Delay ms */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_initialize(UX_HCD *hcd) +{ + +UX_HCD_EHCI *hcd_ehci; +UX_EHCI_ED *ed; +UX_EHCI_LINK_POINTER lp; +ULONG ehci_register; +ULONG port_index; +UINT status = UX_SUCCESS; + + + /* The controller initialized here is of EHCI type. */ + hcd -> ux_hcd_controller_type = UX_EHCI_CONTROLLER; + + /* Initialize the max bandwidth for periodic endpoints. On EHCI, + the spec says no more than 90% to be allocated for periodic. */ + hcd -> ux_hcd_available_bandwidth = UX_EHCI_AVAILABLE_BANDWIDTH; + + /* Allocate memory for this EHCI HCD instance. */ + hcd_ehci = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HCD_EHCI)); + if (hcd_ehci == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Set the pointer to the EHCI HCD. */ + hcd -> ux_hcd_controller_hardware = (VOID *) hcd_ehci; + + /* Save the register memory address. */ + hcd_ehci -> ux_hcd_ehci_base = (ULONG *) hcd -> ux_hcd_io; + + /* Obtain the address of the HCOR registers. This is a byte offset from the + HCOR Cap registers. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCCR_CAP_LENGTH); + hcd_ehci -> ux_hcd_ehci_hcor = (ehci_register & 0xff) >> 2; + + /* Set the generic HCD owner for the EHCI HCD. */ + hcd_ehci -> ux_hcd_ehci_hcd_owner = hcd; + + /* Initialize the function entry for this HCD. */ + hcd -> ux_hcd_entry_function = _ux_hcd_ehci_entry; + + /* Set the state of the controller to HALTED first. */ + hcd -> ux_hcd_status = UX_HCD_STATUS_HALTED; + + /* Read the EHCI Controller Command register. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_USB_COMMAND); + + /* Isolate the Frame list size. */ + ehci_register = (ehci_register >> 2) & 3; + + /* Frame list size selection. */ + switch (ehci_register) + { + + case 0 : + + /* Frame list size is 1024 entries. */ + hcd_ehci -> ux_hcd_ehci_frame_list_size = 1024; + break; + + case 1 : + + /* Frame list size is 512 entries. */ + hcd_ehci -> ux_hcd_ehci_frame_list_size = 512; + break; + case 2 : + + /* Frame list size is 256 entries. */ + hcd_ehci -> ux_hcd_ehci_frame_list_size = 256; + break; + + default : + + /* Error, Wrong frame size. This should never happen. */ + status = (UX_ERROR); + } + + /* Allocate the EHCI controller frame list. The memory alignment is 4K. + The number of entries may be changeable in some controllers. We get the value in the command register. */ + if (status == UX_SUCCESS) + { + hcd_ehci -> ux_hcd_ehci_frame_list = _ux_utility_memory_allocate(UX_ALIGN_4096, UX_CACHE_SAFE_MEMORY, (hcd_ehci -> ux_hcd_ehci_frame_list_size * 4)); + if (hcd_ehci -> ux_hcd_ehci_frame_list == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + } + + /* Allocate the list of eds. All eds are allocated on 32 byte memory boundary. */ + if (status == UX_SUCCESS) + { + hcd_ehci -> ux_hcd_ehci_ed_list = _ux_utility_memory_allocate(UX_ALIGN_32, UX_CACHE_SAFE_MEMORY, sizeof(UX_EHCI_ED) * _ux_system_host -> ux_system_host_max_ed); + if (hcd_ehci -> ux_hcd_ehci_ed_list == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + } + + /* Allocate the list of tds. All tds are allocated on 32 byte memory boundary. */ + if (status == UX_SUCCESS) + { + hcd_ehci -> ux_hcd_ehci_td_list = _ux_utility_memory_allocate(UX_ALIGN_32, UX_CACHE_SAFE_MEMORY, sizeof(UX_EHCI_TD) * _ux_system_host -> ux_system_host_max_td); + if (hcd_ehci -> ux_hcd_ehci_td_list == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + } + +#if UX_MAX_ISO_TD == 0 || !defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + hcd_ehci -> ux_hcd_ehci_fsiso_td_list = UX_NULL; +#else + + /* Allocate the list of isochronous Full Speed tds. All tds are allocated on 32 byte + memory boundary. */ + if (status == UX_SUCCESS) + { + hcd_ehci -> ux_hcd_ehci_fsiso_td_list = _ux_utility_memory_allocate(UX_ALIGN_32, UX_CACHE_SAFE_MEMORY, sizeof(UX_EHCI_FSISO_TD) * _ux_system_host -> ux_system_host_max_iso_td); + if (hcd_ehci -> ux_hcd_ehci_fsiso_td_list == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + } +#endif + +#if UX_MAX_ISO_TD == 0 + hcd_ehci -> ux_hcd_ehci_hsiso_td_list = UX_NULL; +#else + + /* Allocate the list of isochronous High Speed tds. All tds are allocated on 32 byte memory boundary. */ + if (status == UX_SUCCESS) + { + hcd_ehci -> ux_hcd_ehci_hsiso_td_list = _ux_utility_memory_allocate(UX_ALIGN_64, UX_CACHE_SAFE_MEMORY, sizeof(UX_EHCI_HSISO_TD) * _ux_system_host -> ux_system_host_max_iso_td); + if (hcd_ehci -> ux_hcd_ehci_hsiso_td_list == UX_NULL) + status = (UX_MEMORY_INSUFFICIENT); + } +#endif + + /* Initialize the periodic tree. */ + if (status == UX_SUCCESS) + status = _ux_hcd_ehci_periodic_tree_create(hcd_ehci); + + if (status == UX_SUCCESS) + { + + /* Since this is a USB 2.0 controller, we can safely hardwire the version. */ + hcd -> ux_hcd_version = 0x200; + + /* The EHCI Controller should not be running. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_USB_COMMAND); + ehci_register &= ~EHCI_HC_IO_RS; + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_USB_COMMAND, ehci_register); + _ux_utility_delay_ms(2); + + /* Perform a global reset to the controller. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_USB_COMMAND); + ehci_register |= EHCI_HC_IO_HCRESET; + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_USB_COMMAND, ehci_register); + + /* Ensure the reset is complete. */ + while (ehci_register & EHCI_HC_IO_HCRESET) + { + + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_USB_COMMAND); + } + + /* Enable host mode for hardware peripheral. */ + UX_HCD_EHCI_EXT_USB_HOST_MODE_ENABLE(hcd_ehci); + + /* Set the Frame List register of the controller. */ + lp.void_ptr = _ux_utility_physical_address(hcd_ehci -> ux_hcd_ehci_frame_list); + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_FRAME_LIST_BASE_ADDRESS, lp.value); + + /* We need one endpoint to be inserted into the Asynchronous list. */ + ed = _ux_hcd_ehci_ed_obtain(hcd_ehci); + if (ed == UX_NULL) + status = (UX_NO_ED_AVAILABLE); + } + + if (status == UX_SUCCESS) + { + + /* Make this ED point to itself. */ + lp.void_ptr = _ux_utility_physical_address(ed); + + /* Store the physical address of this Ed into the asynch list. */ + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_ASYNCH_LIST_ADDRESS, lp.value); + + /* Store LP with QH Typ. */ + lp.value |= UX_EHCI_QH_TYP_QH; + ed -> ux_ehci_ed_queue_head = lp.ed_ptr; + + /* This ED will be the HEAD ED in the asynch list. */ + ed -> ux_ehci_ed_cap0 = UX_EHCI_QH_HEAD; + + /* We keep this ED as being the first, the last and the head ED. */ + hcd_ehci -> ux_hcd_ehci_asynch_head_list = ed; + hcd_ehci -> ux_hcd_ehci_asynch_first_list = ed; + hcd_ehci -> ux_hcd_ehci_asynch_last_list = ed; + + /* Set the EHCI Interrupt threshold default value (1 or 8 per ms) + and the size of the frame list. */ + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_USB_COMMAND, EHCI_HC_IO_ITC); + + /* Get the number of ports on the controller. The number of ports + needs to be reflected both for the generic HCD container and the + local ehci container. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCCR_HCS_PARAMS); + hcd -> ux_hcd_nb_root_hubs = (UINT) (ehci_register & 0xf); + hcd_ehci -> ux_hcd_ehci_nb_root_hubs = (UINT) (ehci_register & 0xf); + + /* The controller transceiver can now send the device connection/extraction + signals to the EHCI controller. */ + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_CONFIG_FLAG, UX_EHCI_ROUTE_TO_LOCAL_HC); + + /* Create mutex for periodic list modification. */ + status = _ux_utility_mutex_create(&hcd_ehci -> ux_hcd_ehci_periodic_mutex, "ehci_periodic_mutex"); + if (status != UX_SUCCESS) + status = (UX_MUTEX_ERROR); + } + + /* We must enable the HCD protection semaphore. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&hcd_ehci -> ux_hcd_ehci_protect_semaphore, "ux_hcd_protect_semaphore", 1); + if (status != UX_SUCCESS) + status = (UX_SEMAPHORE_ERROR); + } + + /* We must enable the HCD doorbell semaphore. */ + if (status == UX_SUCCESS) + { + status = _ux_utility_semaphore_create(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore, "ux_hcd_doorbell_semaphore", 0); + if (status != UX_SUCCESS) + status = (UX_SEMAPHORE_ERROR); + } + + if (status == UX_SUCCESS) + { + + /* The EHCI Controller can now be Started. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_USB_COMMAND); + + /* Set the Frame list size and the RUN bit.. */ + ehci_register |= UX_EHCI_FRAME_LIST_MASK + | EHCI_HC_IO_RS + | EHCI_HC_IO_ASE + | EHCI_HC_IO_PSE; + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_USB_COMMAND, ehci_register); + + /* Regular EHCI with embedded TT. */ + hcd_ehci -> ux_hcd_ehci_embedded_tt = UX_HCD_EHCI_EXT_EMBEDDED_TT_SUPPORT; + + /* All ports must now be powered to pick up device insertion. */ + _ux_hcd_ehci_power_root_hubs(hcd_ehci); + + /* Set the state of the controller to OPERATIONAL. */ + hcd -> ux_hcd_status = UX_HCD_STATUS_OPERATIONAL; + + /* Set the EHCI Interrupt Register. */ + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_USB_INTERRUPT, EHCI_HC_INTERRUPT_ENABLE_NORMAL); + + /* The controller interrupt must have a handler and be active now. */ + _ux_utility_set_interrupt_handler(hcd -> ux_hcd_irq, _ux_hcd_ehci_interrupt_handler); + + + /* Force a enum process if CCS detected. + ** Because CSC may keep zero in this case. + */ + for (port_index = 0, status = 0; port_index < hcd_ehci -> ux_hcd_ehci_nb_root_hubs; port_index ++) + { + + /* Read register. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_PORT_SC + port_index); + + /* Check CCS. */ + if (ehci_register & EHCI_HC_PS_CCS) + { + hcd_ehci -> ux_hcd_ehci_hcd_owner -> ux_hcd_root_hub_signal[port_index]++; + status ++; + } + } + + /* Wakeup enum thread. */ + if (status != 0) + _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); + + /* Return successful status. */ + return(UX_SUCCESS); + } + + /* Error! Free resources! */ + if (hcd_ehci -> ux_hcd_ehci_frame_list) + _ux_utility_memory_free(hcd_ehci -> ux_hcd_ehci_frame_list); + if (hcd_ehci -> ux_hcd_ehci_ed_list) + _ux_utility_memory_free(hcd_ehci -> ux_hcd_ehci_ed_list); + if (hcd_ehci -> ux_hcd_ehci_td_list) + _ux_utility_memory_free(hcd_ehci -> ux_hcd_ehci_td_list); +#if UX_MAX_ISO_TD && defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (hcd_ehci -> ux_hcd_ehci_fsiso_td_list) + _ux_utility_memory_free(hcd_ehci -> ux_hcd_ehci_fsiso_td_list); +#endif +#if UX_MAX_ISO_TD + if (hcd_ehci -> ux_hcd_ehci_hsiso_td_list) + _ux_utility_memory_free(hcd_ehci -> ux_hcd_ehci_hsiso_td_list); +#endif + if (hcd_ehci -> ux_hcd_ehci_periodic_mutex.tx_mutex_id != 0) + _ux_utility_mutex_delete(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + if (hcd_ehci -> ux_hcd_ehci_protect_semaphore.tx_semaphore_id != 0) + _ux_utility_semaphore_delete(&hcd_ehci -> ux_hcd_ehci_protect_semaphore); + if (hcd_ehci -> ux_hcd_ehci_doorbell_semaphore.tx_semaphore_id != 0) + _ux_utility_semaphore_delete(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore); + _ux_utility_memory_free(hcd_ehci); + + /* Return error status code. */ + return(status); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_endpoint_create.c b/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_endpoint_create.c new file mode 100644 index 0000000..17166f1 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_endpoint_create.c @@ -0,0 +1,400 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_interrupt_endpoint_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will create an interrupt endpoint. The interrupt */ +/* endpoint has an interval of operation from 1 to 255. In EHCI, the */ +/* hardware assisted interrupt is from 1 to 32. */ +/* */ +/* This routine will match the best interval for the EHCI hardware. */ +/* It will also determine the best node to hook the endpoint based on */ +/* the load that already exists on the horizontal ED chain. */ +/* */ +/* For the ones curious about this coding. The tricky part is to */ +/* understand how the interrupt matrix is constructed. We have used */ +/* eds with the skip bit on to build a frame of anchor eds. Each ED */ +/* creates a node for an appropriate combination of interval frequency */ +/* in the list. */ +/* */ +/* After obtaining a pointer to the list with the lowest traffic, we */ +/* traverse the list from the highest interval until we reach the */ +/* interval required. At that node, we anchor our real ED to the node */ +/* and link the ED that was attached to the node to our ED. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_ed_obtain Obtain an ED */ +/* _ux_hcd_ehci_least_traffic_list_get Get least traffic list */ +/* _ux_hcd_ehci_poll_rate_entry_get Get anchor for poll rate */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_mutex_on Get mutex */ +/* _ux_utility_mutex_off Put mutex */ +/* _ux_hcd_ehci_periodic_descriptor_link Link/unlink descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_interrupt_endpoint_create(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint) +{ + +UX_DEVICE *device; +UX_EHCI_ED *ed; +UX_EHCI_ED *ed_list; +UX_EHCI_ED *ed_anchor; +UINT interval; +UINT poll_depth; +ULONG max_packet_size; +ULONG num_transaction; +ULONG microframe_load[8]; +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) +ULONG microframe_ssplit_count[8]; +UINT csplit_count; +ULONG cmask; +#else +#define microframe_ssplit_count UX_NULL +#endif +UX_EHCI_PERIODIC_LINK_POINTER lp; +UINT i; + + + /* Get the pointer to the device. */ + device = endpoint -> ux_endpoint_device; + +#if !defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + + /* Only high speed transfer supported without split transfer. */ + if (device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + return(UX_FUNCTION_NOT_SUPPORTED); +#endif + + /* Obtain a ED for this new endpoint. This ED will live as long as the endpoint is + active and will be the container for the tds. */ + ed = _ux_hcd_ehci_ed_obtain(hcd_ehci); + if (ed == UX_NULL) + return(UX_NO_ED_AVAILABLE); + + /* Attach the ED to the endpoint container. */ + endpoint -> ux_endpoint_ed = (VOID *) ed; + + /* Now do the opposite, attach the ED container to the physical ED. */ + ed -> ux_ehci_ed_endpoint = endpoint; + + /* Set the default MPS Capability info in the ED. */ + max_packet_size = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_PACKET_SIZE_MASK; + ed -> ux_ehci_ed_cap0 = max_packet_size << UX_EHCI_QH_MPS_LOC; + + /* Set the device address. */ + ed -> ux_ehci_ed_cap0 |= device -> ux_device_address; + + /* Add the endpoint address. */ + ed -> ux_ehci_ed_cap0 |= (endpoint -> ux_endpoint_descriptor.bEndpointAddress & ~UX_ENDPOINT_DIRECTION) << UX_EHCI_QH_ED_AD_LOC; + + /* Set the High Bandwidth Pipe Multiplier to number transactions. */ + num_transaction = (endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK) >> UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT; + if (num_transaction < 3) + num_transaction ++; + ed -> ux_ehci_ed_cap1 |= (num_transaction << UX_EHCI_QH_HBPM_LOC); + + /* Set the device speed for full and low speed devices behind a HUB. The HUB address and the + port index must be stored in the endpoint. For low/full speed devices, the C-mask field must be set. */ + switch (device -> ux_device_speed) + { + + case UX_HIGH_SPEED_DEVICE: + ed -> ux_ehci_ed_cap0 |= UX_EHCI_QH_HIGH_SPEED; + break; + + case UX_LOW_SPEED_DEVICE: + ed -> ux_ehci_ed_cap0 |= UX_EHCI_QH_LOW_SPEED; + + /* Fall through. */ + default: + + /* The device must be on a hub for this code to execute. We still do a sanity check. */ + if (device -> ux_device_parent != UX_NULL) + { + + /* Store the parent hub device address. */ + ed -> ux_ehci_ed_cap1 |= device -> ux_device_parent -> ux_device_address << UX_EHCI_QH_HUB_ADDR_LOC; + + /* And the port index onto which this device is attached. */ + ed -> ux_ehci_ed_cap1 |= device -> ux_device_port_location << UX_EHCI_QH_PORT_NUMBER_LOC; + } + break; + } + + /* Get the interval for the endpoint and match it to a EHCI list. + We match anything that is > 32ms to the 32ms interval layer. + The 32ms list is layer 5, 16ms list is 4 ... the 1ms list is depth 0. */ + interval = endpoint -> ux_endpoint_descriptor.bInterval; +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + + /* Convert from ms to 2^i. */ + for (i = 0; i < 16; i ++) + { + if (interval <= (1u << i)) + break; + } + + /* Index 0 for 1ms (interval 4). */ + interval = 4 + i; + } + else +#endif + { + /* High-speed interval is 2^(interval - 1) * 1/2^3. */ + if (interval <= 4) + i = 0; + else + i = interval - 4; + + /* Index 0 for 1ms. */ + } + + /* Match > 32ms to 32ms list. */ + /* Poll depth deeper, interval smaller. */ + if (i > 5) + poll_depth = 0; + else + poll_depth = 5 - i; + + /* Keep interval < 1ms for micro-frame calculation. */ + /* Make it index steps to move. */ + if (interval > 0) + { + interval --; + interval &= 0x3; + } + interval = (1u << interval); /* 1 (1/8ms), 2, 4, 8 (1ms) */ + + /* We are now updating the periodic list. */ + _ux_utility_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + + /* Get the list index with the least traffic. */ + ed_list = _ux_hcd_ehci_least_traffic_list_get(hcd_ehci, microframe_load, microframe_ssplit_count); + + /* Now we need to scan the list of eds from the lowest load entry until we reach the + appropriate interval node. The depth index is the interval EHCI value and the + 1st entry is pointed by the ED list entry. */ + ed_anchor = _ux_hcd_ehci_poll_rate_entry_get(hcd_ehci, ed_list, poll_depth); + + /* Save anchor pointer for interrupt ED. */ + ed -> ux_ehci_ed_anchor = ed_anchor; + + /* Calculate packet size with num transactions. */ + max_packet_size *= num_transaction; + + /* Go through the transaction loads for start + index of micro-frame. */ + for (i = 0; i < interval; i ++) + { + + /* Skip if load too much. */ + if (microframe_load[i] + max_packet_size > UX_MAX_BYTES_PER_MICROFRAME_HS) + continue; + +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + + /* Skip Y6 since host must not use it. */ + if (i == 6) + continue; + + /* Skip if start split count over 16 split. */ + if (microframe_ssplit_count[i] >= 16) + continue; + } +#endif + + /* Use the load. */ + break; + } + + /* Sanity check, bandwidth checked before endpoint creation so there should + not be error but we check it any way. */ + if (i >= interval) + { + _ux_utility_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + ed -> ux_ehci_ed_status = UX_UNUSED; + return(UX_NO_BANDWIDTH_AVAILABLE); + } + + /* Now start microframe index is calculated, build masks. */ + + /* It's interval is larger than 1ms, use any of micro-frame. */ + if (interval >= 8) + { + + /* Interrupt schedule. */ + ed -> ux_ehci_ed_cap1 |= (UX_EHCI_SMASK_0 << i); + +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + /* For split transfer, complete split should be scheduled. */ + if (device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + + /* Interrupt IN/OUT: + must schedule a complete-split transaction in each of the two + microframes following the first microframe in which the + full/low speed transaction is budgeted. An additional + complete-split must also be scheduled in the third following + microframe unless the full/low speed transaction was budgeted + to start in Y6. */ + + if (i == 5) + { + + /* Budgeted in Y6, Follow two (C7, C0). */ + cmask = UX_EHCI_CMASK_INT_Y5; + csplit_count = 2; + } + else + { + + /* Follow three. */ + cmask = UX_EHCI_CMASK_INT_Y0 << i; + if (i > 3) + { + cmask |= cmask >> 8; + cmask &= UX_EHCI_CMASK_MASK; + } + csplit_count = 3; + } + + /* Reserve count for SSplit (Max 16). */ + ed_anchor -> ux_ehci_ed_microframe_ssplit_count[i] ++; + + /* Reserve packet bytes for microframe load. */ + if (endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) + { + + /* Reserve load for CSplit. */ + ed_anchor -> ux_ehci_ed_microframe_load[(i + 2)&7] += max_packet_size; + ed_anchor -> ux_ehci_ed_microframe_load[(i + 3)&7] += max_packet_size; + + /* Need additional CSplit. */ + if (csplit_count > 2) + ed_anchor -> ux_ehci_ed_microframe_load[(i + 4)&7] += max_packet_size; + } + else + { + + /* Reserve load for SSplit. */ + ed_anchor -> ux_ehci_ed_microframe_load[i] += max_packet_size; + } + + /* Update schedule masks. */ + ed -> ux_ehci_ed_cap1 |= cmask; + } + else +#endif + { + /* Update anchor micro-frame load. */ + ed_anchor -> ux_ehci_ed_microframe_load[i] += max_packet_size; + } + } + else + { + + /* It must be high speed high bandwidth one. */ + switch(interval) + { + case 1: + ed -> ux_ehci_ed_cap1 |= UX_EHCI_SMASK_INTERVAL_1; + break; + case 2: + ed -> ux_ehci_ed_cap1 |= UX_EHCI_SMASK_INTERVAL_2 << i; + break; + default: /* 4, interval 3, 1/2ms */ + ed -> ux_ehci_ed_cap1 |= UX_EHCI_SMASK_INTERVAL_3 << i; + break; + } + + /* Update anchor micro-frame loads. */ + for (; i < 8; i += interval) + ed_anchor -> ux_ehci_ed_microframe_load[i] += max_packet_size; + } + + /* We found the node entry of the ED pointer that will be the anchor for this interrupt + endpoint. Now we attach this endpoint to the anchor and rebuild the chain. */ + + /* Physical LP, with Typ QH, clear T. */ + lp.void_ptr = _ux_utility_physical_address(ed); + lp.value |= UX_EHCI_TYP_QH; + + /* Save previous LP: to anchor. */ + ed -> ux_ehci_ed_previous_ed = ed_anchor; + + /* Link the QH at next to anchor. */ + _ux_hcd_ehci_periodic_descriptor_link(ed_anchor, lp.void_ptr, ed, ed_anchor -> ux_ehci_ed_queue_head); + + /* Insert ED to interrupt scan list for fast done queue scan. */ + ed -> ux_ehci_ed_next_ed = hcd_ehci -> ux_hcd_ehci_interrupt_ed_list; + hcd_ehci -> ux_hcd_ehci_interrupt_ed_list = ed; + + /* Release the periodic list. */ + _ux_utility_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + + /* Return successful completion. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_endpoint_destroy.c b/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_endpoint_destroy.c new file mode 100644 index 0000000..fbcc385 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_endpoint_destroy.c @@ -0,0 +1,195 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_interrupt_endpoint_destroy PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will destroy an interrupt endpoint. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_door_bell_wait Setup doorbell wait */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_mutex_on Get mutex */ +/* _ux_utility_mutex_off Put mutex */ +/* _ux_hcd_ehci_periodic_descriptor_link Link/unlink descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_interrupt_endpoint_destroy(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint) +{ + +UX_EHCI_ED *ed; +UX_EHCI_ED *prev_ed; +ULONG frindex; +ULONG max_packet_size; + + + /* From the endpoint container fetch the EHCI ED descriptor. */ + ed = (UX_EHCI_ED *) endpoint -> ux_endpoint_ed; + + /* Access to periodic list. */ + _ux_utility_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + + /* Unlink the periodic item. */ + _ux_hcd_ehci_periodic_descriptor_link(ed -> ux_ehci_ed_previous_ed, + UX_NULL, UX_NULL, ed -> ux_ehci_ed_queue_head); + + /* Update the interrupt ED scan list. */ + prev_ed = hcd_ehci -> ux_hcd_ehci_interrupt_ed_list; + + /* Check if ED in head of scan list. */ + if (prev_ed == ed) + + /* Point head to the next ED. */ + hcd_ehci -> ux_hcd_ehci_interrupt_ed_list = ed -> ux_ehci_ed_next_ed; + else + { + + /* Try to find previous ED in scan list. */ + /* It's at head now. */ + while(prev_ed -> ux_ehci_ed_next_ed) + { + + /* The expected ED is found. */ + if (prev_ed -> ux_ehci_ed_next_ed == ed) + { + + /* Point next to next of the ED. */ + prev_ed -> ux_ehci_ed_next_ed = ed -> ux_ehci_ed_next_ed; + break; + } + + /* Try next ED. */ + prev_ed = prev_ed -> ux_ehci_ed_next_ed; + } + } + + /* Update micro-frame loads of anchor. */ + + /* Calculate max packet size. */ +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + max_packet_size = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_PACKET_SIZE_MASK; + else +#endif + { + max_packet_size = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK; + max_packet_size >>= UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT; + if (max_packet_size < 3) + max_packet_size ++; + max_packet_size *= endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_PACKET_SIZE_MASK; + } + + /* Update according to ED S-Mask. */ + for(frindex = 0; frindex < 8; frindex ++) + { + + /* Check schedule mask. */ + if ((ed -> ux_ehci_ed_cap1 & (UX_EHCI_SMASK_0 << frindex))) + { + +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + + /* Start split check. */ + if (endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + + /* Decrement the start split count. */ + ed -> ux_ehci_ed_anchor -> ux_ehci_ed_microframe_ssplit_count[frindex] --; + + /* Check next endpoint if it's IN (load in C-Mask). */ + if (endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) + continue; + } +#endif + /* Decrement the microframe load. */ + ed -> ux_ehci_ed_anchor -> ux_ehci_ed_microframe_load[frindex] -= max_packet_size; + + /* S-Mask found, no C-Mask at the same time, skip C-Mask check. */ + continue; + } + +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + + /* Complete split interrupt IN check in C-Mask. */ + if ((endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) && + (endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) && + (ed -> ux_ehci_ed_cap1 & (UX_EHCI_CMASK_0 << frindex))) + { + + /* Decrement the microframe load. */ + ed -> ux_ehci_ed_anchor -> ux_ehci_ed_microframe_load[frindex] -= max_packet_size; + } +#endif + } + + /* Release periodic list. */ + _ux_utility_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + + /* Arm the doorbell and wait for its completion. */ + _ux_hcd_ehci_door_bell_wait(hcd_ehci); + + /* Now we can safely make the ED free. */ + ed -> ux_ehci_ed_status = UX_UNUSED; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_handler.c b/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_handler.c new file mode 100644 index 0000000..e304a7b --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_interrupt_handler.c @@ -0,0 +1,189 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_interrupt_handler PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the interrupt handler for the EHCI interrupts. */ +/* Normally an interrupt occurs from the controller when there is */ +/* either a EOF signal and there has been transfers within the frame */ +/* or when there is a change on one of the downstream ports, a */ +/* doorbell signal or an unrecoverable error. */ +/* */ +/* All we need to do in the ISR is scan the controllers to find out */ +/* which one has issued a IRQ. If there is work to do for this */ +/* controller we need to wake up the corresponding thread to take care */ +/* of the job. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_controller_disable Disable controller */ +/* _ux_hcd_ehci_register_read Read EHCI register */ +/* _ux_hcd_ehci_register_write Write EHCI register */ +/* _ux_utility_semaphore_put Put semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ehci_interrupt_handler(VOID) +{ + +UINT hcd_index; +UX_HCD *hcd; +UX_HCD_EHCI *hcd_ehci; +ULONG ehci_register; +ULONG ehci_register_port_status; +ULONG root_hub_thread_wakeup = 0; +ULONG port_index; + + + /* We need to parse the controller driver table to find all controllers that registered + as EHCI. */ + for (hcd_index = 0; hcd_index < _ux_system_host -> ux_system_host_registered_hcd; hcd_index++) + { + + /* Check type of controller. */ + if (_ux_system_host -> ux_system_host_hcd_array[hcd_index].ux_hcd_controller_type == UX_EHCI_CONTROLLER) + { + + /* Get the pointers to the generic HCD and EHCI specific areas. */ + hcd = &_ux_system_host -> ux_system_host_hcd_array[hcd_index]; + hcd_ehci = (UX_HCD_EHCI *) hcd -> ux_hcd_controller_hardware; + + /* Check if the controller is operational, if not, skip it. */ + if (hcd -> ux_hcd_status == UX_HCD_STATUS_OPERATIONAL) + { + + /* For debugging purposes, increment the interrupt count. */ + hcd_ehci -> ux_hcd_ehci_interrupt_count++; + + /* We get the current interrupt status for this controller. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_USB_STATUS); + + /* We acknowledge the interrupts for this controller so that it + can continue to work. */ + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_USB_STATUS, ehci_register); + + /* Examine the source of interrupts. */ + if ((ehci_register & EHCI_HC_STS_USB_INT) || (ehci_register & EHCI_HC_STS_USB_ERR_INT)) + { + + /* We have some transactions done in the past frame/micro-frame. + The controller thread needs to wake up and process them. */ + hcd -> ux_hcd_thread_signal++; + _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + } + + if (ehci_register & EHCI_HC_STS_HSE) + { + + /* The controller has issued a Host System Error which is fatal. + The controller will be reset now, and we wake up the HCD thread. */ + _ux_hcd_ehci_controller_disable(hcd_ehci); + hcd -> ux_hcd_thread_signal++; + hcd -> ux_hcd_status = UX_HCD_STATUS_DEAD; + hcd -> ux_hcd_thread_signal++; + _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_INTERRUPT, UX_SYSTEM_CONTEXT_HCD, UX_CONTROLLER_DEAD); + + } + + if (ehci_register & EHCI_HC_STS_PCD) + { + + /* The controller has issued a Root hub status change signal. Scan all ports. */ + for (port_index = 0; port_index < hcd_ehci -> ux_hcd_ehci_nb_root_hubs; port_index++) + { + + /* Read the port status. */ + ehci_register_port_status = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_PORT_SC + port_index); + + /* Check for Connect Status Change signal. */ + if (ehci_register_port_status & EHCI_HC_PS_CSC) + { + /* Something happened on this port. Signal it to the root hub thread. */ + hcd -> ux_hcd_root_hub_signal[port_index]++; + + /* Memorize wake up signal. */ + root_hub_thread_wakeup ++; + + } + + } + + /* We only wake up the root hub thread if there has been device insertion/extraction. */ + if (root_hub_thread_wakeup != 0) + + /* The controller has issued a Root hub status change signal. + We need to resume the thread in charge of the USB topology. */ + _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); + } + + if (ehci_register & EHCI_HC_STS_IAA) + { + + /* The controller has issued a Door Bell status change signal. + We need to resume the thread who raised the doorbell. */ + _ux_utility_semaphore_put(&hcd_ehci -> ux_hcd_ehci_doorbell_semaphore); + } + } + } + } +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_isochronous_endpoint_create.c b/common/usbx_host_controllers/src/ux_hcd_ehci_isochronous_endpoint_create.c new file mode 100644 index 0000000..0b1ae42 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_isochronous_endpoint_create.c @@ -0,0 +1,546 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_isochronous_endpoint_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will create an isochronous endpoint. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_allocate Allocate memory */ +/* _ux_utility_memory_free Free memory */ +/* _ux_hcd_ehci_hsisochronous_td_obtain Obtain a TD */ +/* _ux_hcd_ehci_least_traffic_list_get Get least traffic list */ +/* _ux_hcd_ehci_poll_rate_entry_get Get anchor for poll rate */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_mutex_on Get mutex */ +/* _ux_utility_mutex_off Put mutex */ +/* _ux_hcd_ehci_periodic_descriptor_link Link/unlink descriptor */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_isochronous_endpoint_create(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint) +{ +#if UX_MAX_ISO_TD == 0 + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Not supported, return error. */ + return(UX_FUNCTION_NOT_SUPPORTED); +#else + +UX_DEVICE *device; +UX_EHCI_HSISO_ED *ed; +UX_EHCI_PERIODIC_LINK_POINTER itd; +UX_EHCI_ED *ed_list; +UX_EHCI_ED *ed_anchor; +UX_EHCI_PERIODIC_LINK_POINTER lp; +UX_EHCI_POINTER bp; +UCHAR interval; +UCHAR interval_shift; +UINT poll_depth; +ULONG microframe_load[8]; +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) +ULONG microframe_ssplit_count[8]; +ULONG mask; +UINT split_count; +ULONG split_last_size; +#else +#define microframe_ssplit_count UX_NULL +#endif +ULONG microframe_i; +ULONG endpt; +ULONG device_address; +ULONG max_packet_size; +ULONG max_trans_size; +ULONG mult; +ULONG io; +UINT i; +UINT status; + + + /* Get the pointer to the device. */ + device = endpoint -> ux_endpoint_device; + + /* Get the interval value from endpoint descriptor. */ + interval = endpoint -> ux_endpoint_descriptor.bInterval; + + /* For ISO, interval 1 ~ 16, means 2^(n-1). */ + if (interval == 0) + interval = 1; + if (interval > 16) + interval = 16; + + /* Interval shift is base 0. */ + interval_shift = interval - 1; + + /* Keep interval as number of micro-frames. */ + interval = (1u << interval_shift); + + /* Get max packet size. */ + max_packet_size = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_PACKET_SIZE_MASK; + + /* Get number transactions per micro-frame. */ + mult = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK; + mult >>= UX_MAX_NUMBER_OF_TRANSACTIONS_SHIFT; + if (mult < 3) + mult ++; + + /* Get max transfer size. */ + max_trans_size = max_packet_size * mult; + + /* Get the Endpt, Device Address, I/O, Maximum Packet Size, Mult. */ + endpt = (endpoint -> ux_endpoint_descriptor.bEndpointAddress << UX_EHCI_HSISO_ENDPT_SHIFT) & UX_EHCI_HSISO_ENDPT_MASK; + device_address = device -> ux_device_address & UX_EHCI_HSISO_DEVICE_ADDRESS_MASK; + io = (endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) ? UX_EHCI_HSISO_DIRECTION_IN : UX_EHCI_HSISO_DIRECTION_OUT; + + /* Only high speed transfer supported without split transfer. */ + if (device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { +#if !defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + return(UX_FUNCTION_NOT_SUPPORTED); +#else + + /* 1 ~ N siTDs ... */ + /* OUT: only start-splits, no complete splits. */ + /* IN : at most one start-split and one to N complete-splits. */ + + /* TBD. */ +#endif + } + else + { + + /* Allocate memory for ED. */ + ed = (UX_EHCI_HSISO_ED *)_ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_EHCI_HSISO_ED)); + if (ed == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Obtain iTDs for this new endpoint. + ** For noncontinuous request address and simplify calculation, allocate + ** one iTD for two microframes. + ** - interval 1 (0): 8 micro-frames, 4 iTD + ** - interval 2 (1): 4 micro-frames, 2 iTD + ** - interval 4 (2): 2 micro-frames, 1 iTD + ** - interval >=8 (3): 1 micro-frame , 1 iTD + ** Two micro-frames in iTD uses BP[3,4] and BP[5,6] to avoid merging of + ** page buffer and iTD settings. + */ + + /* Get number of iTDs should be allocated. */ + if (interval > 2) + ed -> ux_ehci_hsiso_ed_nb_tds = 1; + else + ed -> ux_ehci_hsiso_ed_nb_tds = 4 >> interval_shift; + + /* Obtain iTDs. */ + status = UX_SUCCESS; + for (i = 0; i < ed -> ux_ehci_hsiso_ed_nb_tds; i ++) + { + + /* Get a new free iTD. */ + itd.itd_ptr = _ux_hcd_ehci_hsisochronous_td_obtain(hcd_ehci); + if (itd.itd_ptr == UX_NULL) + { + status = UX_NO_TD_AVAILABLE; + break; + } + + /* Link to ED. */ + itd.itd_ptr -> ux_ehci_hsiso_td_ed = ed; + + /* Save max transfer size. */ + itd.itd_ptr -> ux_ehci_hsiso_td_max_trans_size = max_trans_size; + + /* Save the iTD for the micro-frame(s). */ + ed -> ux_ehci_hsiso_ed_fr_td[i] = itd.itd_ptr; + } + + /* If there is error, free allocated resources. */ + if (status != UX_SUCCESS) + { + for (i = 0; i < ed -> ux_ehci_hsiso_ed_nb_tds; i ++) + ed -> ux_ehci_hsiso_ed_fr_td[i] -> ux_ehci_hsiso_td_status = UX_UNUSED; + _ux_utility_memory_free(ed); + } + + /* Save information not related to periodic things. */ + + /* Save endpoint. */ + ed -> ux_ehci_hsiso_ed_endpoint = endpoint; + + /* Save interval. */ + ed -> ux_ehci_hsiso_ed_frinterval = interval; + ed -> ux_ehci_hsiso_ed_frinterval_shift = interval_shift; + + /* Disable iTDs for now. */ + ed -> ux_ehci_hsiso_ed_frstart = 0xFF; + } + + /* Attach the first iTD as the endpoint container. */ + endpoint -> ux_endpoint_ed = ed -> ux_ehci_hsiso_ed_fr_td[0]; + + /* Match the interval for the endpoint to a EHCI list. + We match anything that is > 32ms to the 32ms interval layer. + The 32ms list is layer 0, 16ms list is 1 ... the 1ms list is depth 5. */ + + /* Match > 32ms to 32ms list. */ + /* Poll depth deeper, interval smaller. */ + if (interval < 4) + poll_depth = 5; + else if (interval > 8) + poll_depth = 0; + else + poll_depth = 8 - interval; + + /* Keep only interval < 1ms for micro-frame calculation. */ + interval_shift &= 0x3; + interval &= 0x7; + + /* Fill the iTDs/siTDs contents that are not related to periodic list. + Initialize the fields to be ready for ZLPs if OUT. + But a zero buffer to underrun IN? */ +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + + /* TBD. */ + } + else +#endif + { + + /* Prepare things not related to periodic things. */ + + for (i = 0; i < ed -> ux_ehci_hsiso_ed_nb_tds; i ++) + { + + /* Get iTD. */ + itd.itd_ptr = ed -> ux_ehci_hsiso_ed_fr_td[i]; + + /* Build next link pointer, if not last one.*/ + if (i < ed -> ux_ehci_hsiso_ed_nb_tds - 1) + { + lp.void_ptr = _ux_utility_physical_address(ed -> ux_ehci_hsiso_ed_fr_td[i + 1]); + itd.itd_ptr -> ux_ehci_hsiso_td_next_lp = lp; + } + + /* Build previous pointer, if not first one. */ + if (i > 0) + { + itd.itd_ptr -> ux_ehci_hsiso_td_previous_lp.itd_ptr = + ed -> ux_ehci_hsiso_ed_fr_td[i - 1]; + } + + /* Save Device Address and Endpt @ BP0. */ + bp.value = device_address | endpt; + itd.itd_ptr -> ux_ehci_hsiso_td_bp[0] = bp.void_ptr; + + /* Save I/O and max packet size @ BP1. */ + bp.value = io | max_packet_size; + itd.itd_ptr -> ux_ehci_hsiso_td_bp[1] = bp.void_ptr; + + /* Save Mult @ BP2. */ + bp.value = mult; + itd.itd_ptr -> ux_ehci_hsiso_td_bp[2] = bp.void_ptr; + } + + } + + /* Lock the periodic list to update. */ + _ux_utility_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + + /* Get the list index with the least traffic. */ + ed_list = _ux_hcd_ehci_least_traffic_list_get(hcd_ehci, microframe_load, microframe_ssplit_count); + + /* Now we need to scan the list of EDs from the lowest load entry until we reach the + appropriate interval node. The depth index is the interval EHCI value and the + 1st entry is pointed by the ED list entry. */ + ed_anchor = _ux_hcd_ehci_poll_rate_entry_get(hcd_ehci, ed_list, poll_depth); + + /* Calculate packet size with num transactions. */ + max_packet_size *= mult; + + /* Go through the transaction loads for for start + index of micro-frame. */ + for (microframe_i = 0; microframe_i < interval; microframe_i ++) + { + + /* Skip if load too much. */ + if (microframe_load[microframe_i] + max_packet_size > UX_MAX_BYTES_PER_MICROFRAME_HS) + continue; + +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + + /* Skip Y6 since host must not use it. */ + if (i == 6) + continue; + + /* Skip if start split count over 16 split. */ + if (microframe_ssplit_count[i] >= 16) + continue; + } +#endif + + /* Use the load. */ + break; + } + + /* Sanity check, bandwidth checked before endpoint creation so there should + not be error but we check it any way. */ + if (microframe_i >= interval) + { + _ux_utility_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + for (i = 0; i < ed -> ux_ehci_hsiso_ed_nb_tds; i ++) + ed -> ux_ehci_hsiso_ed_fr_td[i] -> ux_ehci_hsiso_td_status = UX_UNUSED; + _ux_utility_memory_free(ed); + return(UX_NO_BANDWIDTH_AVAILABLE); + } + + /* Now start microframe index is calculated, things related periodic list. */ +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + /* OUT: each microframe budgeted, 188 (or the remaining data size) data byte. + never complete-split. + IN : complete-split must be scheduled for each following microframe. + L - the last microframe in which a complete-split is scheduled. + L < Y6, schedule additional complete-splits in microframe L+1 and L+2. + L == Y6, schedule one complete-split in microframe Y7, + schedule one complete-split in microframe Y0 of the next frame, + unless the full speed transaction was budgeted to start in microframe Y0. + L == Y7, schedule one complete-split in microframe Y0 of the next frame, + unless the full speed transaction was budgeted to start in microframe Y0. + */ + + /* Save anchor pointer. */ + itd.sitd_ptr -> ux_ehci_fsiso_td_anchor = ed_anchor; + + /* No back pointer by default. */ + lp.value = UX_EHCI_T; + + /* OUT or IN? */ + if (io == 0) + { + + /* Multiple start split based on max packet size, no complete split. */ + split_count = (max_packet_size + 187) / 188; + split_last_size = max_packet_size % 188; + + mask = (UX_EHCI_SMASK_0 << split_count) - UX_EHCI_SMASK_0; + mask <<= microframe_i; + if (microframe_i + split_count > 8) + { + mask |= mask >> 8; + mask &= UX_EHCI_SMASK_MASK; + + /* Need back pointer. */ + lp = itd; + lp.void_ptr = _ux_utility_physical_address(lp.void_ptr); + } + + /* Save settings. */ + itd.sitd_ptr -> ux_ehci_fsiso_td_cap1 = mask; + itd.sitd_ptr -> ux_ehci_fsiso_td_back_pointer = lp.void_ptr; + + /* Update anchor micro-frame loads and start splits. */ + for (i = 0; i < 8; i ++) + { + if ((mask & (UX_EHCI_SMASK_0 << i)) == 0) + continue; + + /* Add to load. */ + if (split_last_size && + i == ((microframe_i + split_count - 1) & 7)) + { + ed_anchor -> ux_ehci_ed_microframe_load[i] += split_last_size; + } + else + ed_anchor -> ux_ehci_ed_microframe_load[i] += 188; + + /* Increment SSplit count. */ + ed_anchor -> ux_ehci_ed_microframe_ssplit_count[i] ++; + } + } + else + { + + /* Single start split. */ + itd.sitd_ptr -> ux_ehci_fsiso_td_cap1 = UX_EHCI_SMASK_0 << microframe_i; + + /* Multiple complete split, start +2, based on max packet size. */ + split_count = (max_packet_size + 187) / 188; + + /* Adding extra 2 at end. */ + split_count += 2; + mask = (UX_EHCI_CMASK_0 << split_count) - UX_EHCI_CMASK_0; + mask <<= microframe_i + 2; + if (microframe_i + 2 + split_count > 8) + { + mask |= mask >> 8; + mask &= UX_EHCI_CMASK_MASK; + + /* Need back pointer. */ + lp = itd; + lp.void_ptr = _ux_utility_physical_address(lp.void_ptr); + } + + /* If Y0 has budget, clear complete mask of it. */ + if (microframe_i == 7) + { + if (mask & UX_EHCI_CMASK_0) + { + mask &= ~UX_EHCI_CMASK_0; + split_count --; + } + } + + /* Save settings. */ + itd.sitd_ptr -> ux_ehci_fsiso_td_cap1 |= mask; + itd.sitd_ptr -> ux_ehci_fsiso_td_back_pointer = lp.void_ptr; + + /* Update anchor micro-frame loads and complete splits. */ + for (i = 0; i < 8; i ++) + { + if ((mask & (UX_EHCI_CMASK_0 << i)) == 0) + continue; + + /* Add to load. */ + ed_anchor -> ux_ehci_ed_microframe_load[i] += 188; + } + + /* Increment SSplit count. */ + ed_anchor -> ux_ehci_ed_microframe_ssplit_count[i] ++; + } + + } + else +#endif + { + + /* Save index base of allocated micro-frame. */ + ed -> ux_ehci_hsiso_ed_frindex = microframe_i; + + /* Save anchor pointer. */ + ed -> ux_ehci_hsiso_ed_anchor = ed_anchor; + + /* Update micro-frames. */ + for (i = microframe_i; i < 8; i += interval) + { + + /* Update anchor micro-frame loads. */ + ed_anchor -> ux_ehci_ed_microframe_load[i] += max_packet_size; + + /* Initialize control with PG -> BP (3, 5). */ + itd.itd_ptr = ed -> ux_ehci_hsiso_ed_fr_td[i >> 1]; + + /* Buffer in page 3,4 or 5,6 to avoid merging settings. */ + if (i & 1u) + itd.itd_ptr -> ux_ehci_hsiso_td_control[i] = UX_EHCI_HSISO_IOC | + (5 << UX_EHCI_HSISO_PG_SHIFT); + else + itd.itd_ptr -> ux_ehci_hsiso_td_control[i] = UX_EHCI_HSISO_IOC | + (3 << UX_EHCI_HSISO_PG_SHIFT); + } + } + + /* Link iTDs to periodic list. */ + + /* Physical LP for anchor (Typ iTD, 0). */ + lp.void_ptr = _ux_utility_physical_address(ed -> ux_ehci_hsiso_ed_fr_td[0]); + + /* Link to periodic list. */ + ed -> ux_ehci_hsiso_ed_fr_td[0] -> ux_ehci_hsiso_td_previous_lp.ed_ptr = ed_anchor; + _ux_hcd_ehci_periodic_descriptor_link(ed_anchor, lp.void_ptr, + ed -> ux_ehci_hsiso_ed_fr_td[ed -> ux_ehci_hsiso_ed_nb_tds - 1], + ed_anchor -> ux_ehci_ed_queue_head); + + /* Simply insert all iTD[0]/siTD[0] to head of scan list. */ +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + itd.sitd_ptr -> ux_ehci_fsiso_td_next_scan_td = hcd_ehci -> ux_hcd_ehci_fsiso_scan_list; + hcd_ehci -> ux_hcd_ehci_fsiso_scan_list = itd.sitd_ptr; + } + else +#endif + { + itd.itd_ptr = ed -> ux_ehci_hsiso_ed_fr_td[0]; + itd.itd_ptr -> ux_ehci_hsiso_td_next_scan_td = + hcd_ehci -> ux_hcd_ehci_hsiso_scan_list; + hcd_ehci -> ux_hcd_ehci_hsiso_scan_list = itd.itd_ptr; + if (itd.itd_ptr -> ux_ehci_hsiso_td_next_scan_td) + itd.itd_ptr -> ux_ehci_hsiso_td_next_scan_td -> ux_ehci_hsiso_td_previous_scan_td = + itd.itd_ptr; + } + + /* Release the periodic table. */ + _ux_utility_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + + /* Return successful completion. */ + return(UX_SUCCESS); +#endif +} diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_isochronous_endpoint_destroy.c b/common/usbx_host_controllers/src/ux_hcd_ehci_isochronous_endpoint_destroy.c new file mode 100644 index 0000000..819f522 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_isochronous_endpoint_destroy.c @@ -0,0 +1,275 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_isochronous_endpoint_destroy PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will destroy an isochronous endpoint. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* _ux_utility_mutex_on Get mutex */ +/* _ux_utility_mutex_off Put mutex */ +/* _ux_hcd_ehci_periodic_descriptor_link Link/unlink descriptor */ +/* _ux_utility_memory_free Free memory */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_isochronous_endpoint_destroy(UX_HCD_EHCI *hcd_ehci, UX_ENDPOINT *endpoint) +{ +#if UX_MAX_ISO_TD == 0 + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Not supported, return error. */ + return(UX_FUNCTION_NOT_SUPPORTED); +#else + +UX_EHCI_HSISO_ED *ed; +UX_EHCI_PERIODIC_LINK_POINTER ed_td; +UX_EHCI_PERIODIC_LINK_POINTER lp; +ULONG max_packet_size; +UINT frindex; +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) +ULONG split_count; +ULONG last_frindex; +ULONG last_size; +#endif + + + /* Get ED iTD/siTD. */ + ed_td.void_ptr = endpoint -> ux_endpoint_ed; + + /* Access to periodic list. */ + _ux_utility_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + + /* Check active iTD/siTD and unlink it. */ +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + /* TBD. */ + } + else +#endif + { + + /* Get ED. */ + ed = ed_td.itd_ptr -> ux_ehci_hsiso_td_ed; + + /* Unlink from periodic list. */ + if (ed_td.itd_ptr -> ux_ehci_hsiso_td_previous_lp.void_ptr != UX_NULL) + { + + /* Get next LP of last iTD. */ + lp = ed -> ux_ehci_hsiso_ed_fr_td[ed -> ux_ehci_hsiso_ed_nb_tds - 1] + -> ux_ehci_hsiso_td_next_lp; + _ux_hcd_ehci_periodic_descriptor_link( + ed_td.itd_ptr -> ux_ehci_hsiso_td_previous_lp.void_ptr, + UX_NULL, UX_NULL, + lp.void_ptr); + } + } + + /* Unlink iTD/siTD from the scan list. */ +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + + /* Get list head. */ + lp.sitd_ptr = hcd_ehci -> ux_hcd_ehci_fsiso_scan_list; + + /* Check if unlink from head. */ + if (lp.sitd_ptr == ed_td.sitd_ptr) + + /* Unlink from list head. */ + hcd_ehci -> ux_hcd_ehci_fsiso_scan_list = ed_td.sitd_ptr -> ux_ehci_fsiso_td_next_scan_td; + else + { + + /* Scan items in list. */ + while(lp.sitd_ptr) + { + + /* Not the previous item, just try next. */ + if (lp.sitd_ptr -> ux_ehci_fsiso_td_next_scan_td != ed_td.sitd_ptr) + { + lp.sitd_ptr = lp.sitd_ptr -> ux_ehci_fsiso_td_next_scan_td; + continue; + } + + /* Found it, unlink and break. */ + lp.sitd_ptr -> ux_ehci_fsiso_td_next_scan_td = ed_td.sitd_ptr -> ux_ehci_fsiso_td_next_scan_td; + break; + } + } + } + else +#endif + { + + /* Get head. */ + lp.itd_ptr = hcd_ehci -> ux_hcd_ehci_hsiso_scan_list; + + /* Check if iTD is in head. */ + if (lp.itd_ptr == ed_td.itd_ptr) + + /* Unlink from list head. */ + hcd_ehci -> ux_hcd_ehci_hsiso_scan_list = lp.itd_ptr -> ux_ehci_hsiso_td_next_scan_td; + else + { + + /* Not in head, there must be previous. */ + + /* Link it's previous to next. */ + lp.itd_ptr -> ux_ehci_hsiso_td_previous_scan_td -> ux_ehci_hsiso_td_next_scan_td = + lp.itd_ptr -> ux_ehci_hsiso_td_next_scan_td; + + /* Link it's next to previous. */ + if (lp.itd_ptr -> ux_ehci_hsiso_td_next_scan_td) + lp.itd_ptr -> ux_ehci_hsiso_td_next_scan_td -> ux_ehci_hsiso_td_previous_scan_td = + lp.itd_ptr -> ux_ehci_hsiso_td_previous_scan_td; + } + } + + /* Update micro-frame loads of anchor. */ + + /* Calculate max packet size. */ +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + max_packet_size = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_PACKET_SIZE_MASK; + + /* Update according to siTD S-Mask. */ + max_packet_size = endpoint -> ux_endpoint_descriptor.wMaxPacketSize & UX_MAX_NUMBER_OF_TRANSACTIONS_MASK; + + /* Update according to mask. */ + + for (frindex = 0; frindex < 8; frindex ++) + { + + /* Update start split related. */ + if (ed_td.sitd_ptr -> ux_ehci_fsiso_td_cap1 & (UX_EHCI_SMASK_0 << frindex)) + { + + /* Update start split count. */ + ed_td.sitd_ptr -> ux_ehci_fsiso_td_anchor -> ux_ehci_ed_microframe_ssplit_count[frindex] --; + + /* Update load for OUT. */ + if ((endpoint -> ux_endpoint_descriptor.bEndpointAddress & UX_ENDPOINT_DIRECTION) == 0) + { + split_count = (max_packet_size + 187) / 188; + last_frindex = ((ed_td.sitd_ptr -> ux_ehci_fsiso_td_frindex + split_count - 1) & 7); + last_size = max_packet_size % 188; + if (last_size == 0 && + frindex == last_frindex) + ed_td.sitd_ptr -> ux_ehci_fsiso_td_anchor -> ux_ehci_ed_microframe_load[frindex] -= last_size; + else + ed_td.sitd_ptr -> ux_ehci_fsiso_td_anchor -> ux_ehci_ed_microframe_load[frindex] -= 188; + } + + } + + /* Update complete split related (IN only). */ + if (ed_td.sitd_ptr -> ux_ehci_fsiso_td_cap1 & (UX_EHCI_CMASK_0 << frindex)) + ed_td.sitd_ptr -> ux_ehci_fsiso_td_anchor -> ux_ehci_ed_microframe_load[frindex] -= 188; + } + } + else +#endif + { + + /* Get max transfer size. */ + max_packet_size = ed_td.itd_ptr -> ux_ehci_hsiso_td_max_trans_size; + + /* Update according to mask. */ + for (frindex = ed -> ux_ehci_hsiso_ed_frindex; + frindex < 8; + frindex += ed -> ux_ehci_hsiso_ed_frinterval) + { + + /* Decrement the microframes scheduled. */ + ed -> ux_ehci_hsiso_ed_anchor -> ux_ehci_ed_microframe_load[frindex] -= max_packet_size; + } + } + + /* Release periodic list. */ + _ux_utility_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + + /* Now we can safely make the iTD/siTDs free. */ +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + ed_td.sitd_ptr -> ux_ehci_fsiso_td_status = UX_UNUSED; + } + else +#endif + { + for (frindex = 0; frindex < ed -> ux_ehci_hsiso_ed_nb_tds; frindex ++) + ed -> ux_ehci_hsiso_ed_fr_td[frindex] -> ux_ehci_hsiso_td_status = UX_UNUSED; + _ux_utility_memory_free(ed); + } + + return(UX_SUCCESS); +#endif +} diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_least_traffic_list_get.c b/common/usbx_host_controllers/src/ux_hcd_ehci_least_traffic_list_get.c new file mode 100644 index 0000000..5d4d06c --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_least_traffic_list_get.c @@ -0,0 +1,165 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_least_traffic_list_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function return a pointer to the first ED in the periodic tree */ +/* that has the least traffic registered. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* microframe_load Pointer to an array for 8 */ +/* micro-frame loads */ +/* microframe_ssplit_count Pointer to an array for 8 */ +/* micro-frame start split count */ +/* */ +/* OUTPUT */ +/* */ +/* UX_EHCI_ED * Pointer to ED */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_EHCI_ED *_ux_hcd_ehci_least_traffic_list_get(UX_HCD_EHCI *hcd_ehci, + ULONG microframe_load[8], ULONG microframe_ssplit_count[8]) +{ + +UX_EHCI_ED *min_bandwidth_ed; +UX_EHCI_ED *ed; +UX_EHCI_PERIODIC_LINK_POINTER anchor; +UINT list_index; +UINT frindex; +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) +UINT bfindex; +#endif +ULONG min_bandwidth_used; +ULONG bandwidth_used; + + +#if !defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + UX_PARAMETER_NOT_USED(microframe_ssplit_count); +#endif + + /* Set the min bandwidth used to a arbitrary maximum value. */ + min_bandwidth_used = 0xffffffff; + + /* The first ED is the list candidate for now. */ + min_bandwidth_ed = *hcd_ehci -> ux_hcd_ehci_frame_list; + + /* All list will be scanned. */ + for (list_index = 0; list_index < 32; list_index++) + { + + /* Reset the bandwidth for this list. */ + bandwidth_used = 0; + + /* Get the ED of the beginning of the list we parse now. */ + /* Obtain the ED address only. */ + /* Obtain the virtual address from the element. */ + anchor.ed_ptr = *(hcd_ehci -> ux_hcd_ehci_frame_list + list_index); + anchor.value &= UX_EHCI_LINK_ADDRESS_MASK; + anchor.void_ptr = _ux_utility_virtual_address(anchor.void_ptr); + + /* Summary micro-frames loads of anchors. */ + /* Reset microframe load table. */ + for (frindex = 0; frindex < 8; frindex ++) + { + microframe_load[frindex] = 0; +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + microframe_ssplit_count[frindex] = 0; +#endif + } + + /* Scan static anchors in the list. */ + ed = anchor.ed_ptr; + while(ed -> ux_ehci_ed_next_anchor != UX_NULL) + { + for (frindex = 0; frindex < 8; frindex ++) + { + microframe_load[frindex] += ed -> ux_ehci_ed_microframe_load[frindex]; +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + microframe_ssplit_count[frindex] += ed -> ux_ehci_ed_microframe_ssplit_count[frindex]; +#endif + } + + /* Next static anchor. */ + ed = ed -> ux_ehci_ed_next_anchor; + } + + /* Summarize bandwidth from micro-frames. */ + for (frindex = 0; frindex < 8; frindex ++) + bandwidth_used += microframe_load[frindex]; + + /* We have processed a list, check the bandwidth used by this list. If this bandwidth is + the minimum, we memorize the ED. */ + if (bandwidth_used < min_bandwidth_used) + { + + /* We have found a better list with a lower used bandwidth, + memorize the bandwidth for this list. */ + min_bandwidth_used = bandwidth_used; + + /* Memorize the ED for this list. */ + min_bandwidth_ed = anchor.ed_ptr; + + /* To optimize time, if bandwidth is 0, we just break the loop. */ + if (min_bandwidth_used == 0) + break; + } + } + + /* Return the ED list with the lowest bandwidth. */ + return(min_bandwidth_ed); +} diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_next_td_clean.c b/common/usbx_host_controllers/src/ux_hcd_ehci_next_td_clean.c new file mode 100644 index 0000000..a027df4 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_next_td_clean.c @@ -0,0 +1,79 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_next_td_clean PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cleans all the tds attached to a ED. The end of the */ +/* TD chain is pointed by the tail TD. */ +/* */ +/* INPUT */ +/* */ +/* TD Pointer to TD */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ehci_next_td_clean(UX_EHCI_TD *td) +{ + + UX_PARAMETER_NOT_USED(td); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_periodic_descriptor_link.c b/common/usbx_host_controllers/src/ux_hcd_ehci_periodic_descriptor_link.c new file mode 100644 index 0000000..bbc7404 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_periodic_descriptor_link.c @@ -0,0 +1,167 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_periodic_descriptor_link PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function link/unlink the iTD/siTD/QH descriptor in periodic */ +/* lists for Host Controller (HC) to scan for transfers in the */ +/* (micro-)frames. */ +/* */ +/* If link_desc is not NULL: */ +/* prev_desc -> physical_next = link_lp */ +/* link_desc -> physical_next = next_desc */ +/* next_desc -> virtual_previous = link_desc */ +/* Resulting sequence prev - link_lp ... link_desc - next_desc. */ +/* */ +/* If link_desc is not NULL: */ +/* prev_desc -> physical_next = link_lp */ +/* next_desc -> virtual_previous = link_desc */ +/* Resulting unlink of things between prev_desc and next_desc. */ +/* */ +/* Note previous LP for linking item is not updated by this function. */ +/* */ +/* INPUT */ +/* */ +/* prev Link Pointer to previous item */ +/* (virtual memory address) */ +/* prev_next Physical link pointer data */ +/* including address, Typ and T. */ +/* If it's NULL the item between */ +/* previous and next is unlinked */ +/* next_prev Link Pointer to item to link */ +/* (virtual memory address) */ +/* next Link pointer to next item */ +/* (physical address, Typ & T) */ +/* */ +/* OUTPUT */ +/* */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +void _ux_hcd_ehci_periodic_descriptor_link( + VOID* prev, + VOID* prev_next, /* for prev -> next_lp. */ + VOID* next_prev, /* for next -> prev_lp (virtual). */ + VOID* next_desc) +{ + +UX_EHCI_PERIODIC_LINK_POINTER virtual_lp; +UX_EHCI_PERIODIC_LINK_POINTER prev_virtual_lp; +UX_EHCI_PERIODIC_LINK_POINTER link_virtual_lp; +UX_EHCI_PERIODIC_LINK_POINTER link_physical_lp; +UX_EHCI_PERIODIC_LINK_POINTER next_physical_lp; + + + /* Pointers. */ + prev_virtual_lp.void_ptr = prev; + link_physical_lp.void_ptr = prev_next; + link_virtual_lp.void_ptr = next_prev; + next_physical_lp.void_ptr = next_desc; + + /* Check link/unlink. */ + if (prev_next && next_prev) + { + + /* Link, fill next LP for linked item first. */ + link_virtual_lp.itd_ptr -> ux_ehci_hsiso_td_next_lp = next_physical_lp; + } + else + { + + /* Unlink, use info from previous and next item. */ + link_virtual_lp = prev_virtual_lp; + link_physical_lp = next_physical_lp; + } + + /* Update LP of previous item for HC to access. */ + prev_virtual_lp.itd_ptr -> ux_ehci_hsiso_td_next_lp = link_physical_lp; + + /* If next item is valid, update its previous LP. */ + if ((next_physical_lp.value & (UX_EHCI_LINK_ADDRESS_MASK | UX_EHCI_T)) != UX_EHCI_T) + { + + /* Get virtual address of next item. */ + virtual_lp.value = next_physical_lp.value & UX_EHCI_LINK_ADDRESS_MASK; + virtual_lp.void_ptr = _ux_utility_virtual_address(virtual_lp.void_ptr); + + /* Update previous LP, except static anchor. */ + switch(next_physical_lp.value & UX_EHCI_TYP_MASK) + { + case UX_EHCI_TYP_ITD: + virtual_lp.itd_ptr -> ux_ehci_hsiso_td_previous_lp = link_virtual_lp; + break; +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + case UX_EHCI_TYP_SITD: + virtual_lp.sitd_ptr -> ux_ehci_fsiso_td_previous_lp = link_virtual_lp; + break; +#endif + default: /* QH. */ + if ((virtual_lp.ed_ptr -> ux_ehci_ed_status & UX_EHCI_QH_STATIC) == 0) + virtual_lp.ed_ptr -> ux_ehci_ed_previous_ed = link_virtual_lp.ed_ptr; + break; + } + } +} + +/* +anchor, next + head, tail ==> anchor, head ... tail, next + head -> prev = anchor (Vir) + anchor -> next = head (Phy) + tail -> next = next (Phy) + next -> prev = tail (Vir) + +anchor, head ... tail, next ==> anchor, next + anchor -> next = next (Phy) + next -> prev = anchor (Vir) + +*/ diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_periodic_tree_create.c b/common/usbx_host_controllers/src/ux_hcd_ehci_periodic_tree_create.c new file mode 100644 index 0000000..c0d14b9 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_periodic_tree_create.c @@ -0,0 +1,185 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_periodic_tree_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates the periodic static tree for the interrupt */ +/* and isochronous eds. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_ed_obtain Obtain an ED */ +/* _ux_utility_physical_address Get physical address */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_periodic_tree_create(UX_HCD_EHCI *hcd_ehci) +{ + +UX_EHCI_ED *ed; +UX_EHCI_ED *previous_ed; +UINT list_index; +UINT list_entries; +UINT current_list_entry; +UX_EHCI_ED *ed_list[32]; +UX_EHCI_ED *ed_start_list[32]; +UX_EHCI_PERIODIC_LINK_POINTER lp; + + /* Start with the 1st list - it has 32 entries. */ + list_entries = 32; + + /* Create each list one by one starting from the 32ms list. */ + for (list_index = 0; list_index < 6; list_index++) + { + + for (current_list_entry = 0; current_list_entry < list_entries; current_list_entry++) + { + + /* In each list, insert an static QH as the anchor. There should not + be any errors when obtaining a new ED, still we do a sanity check. */ + ed = _ux_hcd_ehci_ed_obtain(hcd_ehci); + if (ed == UX_NULL) + return(UX_NO_ED_AVAILABLE); + + /* Mark the anchor as being a QH pointer and a terminator. */ + ed -> ux_ehci_ed_queue_head = (UX_EHCI_ED *) (UX_EHCI_QH_TYP_QH | UX_EHCI_QH_T); + + /* The Queue element has the terminator bit on. */ + ed -> ux_ehci_ed_queue_element = (UX_EHCI_TD *) UX_EHCI_TD_T; + + /* The Alternate TD has the terminator bit on. */ + ed -> ux_ehci_ed_alternate_td = (UX_EHCI_TD *) UX_EHCI_TD_T; + + /* This endpoint is an anchor. */ + ed -> ux_ehci_ed_status |= UX_EHCI_QH_STATIC; + + /* Either we hook this new ED to the start list for further processing + or we hook it to the 2 successive entries in the previous list. */ + if (list_index == 0) + { + + ed_start_list[current_list_entry] = ed; + } + else + { + + /* We need to update the previous ED with the link to this new ED. Since + this is a tree structure, this operation is done twice to the 2 previous + eds in the previous list. */ + lp.void_ptr = _ux_utility_physical_address(ed); + lp.value |= UX_EHCI_QH_TYP_QH; + previous_ed = ed_list[current_list_entry * 2]; + previous_ed -> ux_ehci_ed_queue_head = lp.ed_ptr; + previous_ed -> ux_ehci_ed_next_ed = ed; + previous_ed -> ux_ehci_ed_next_anchor = ed; + previous_ed = ed_list[(current_list_entry * 2) + 1]; + previous_ed -> ux_ehci_ed_queue_head = lp.ed_ptr; + previous_ed -> ux_ehci_ed_next_ed = ed; + previous_ed -> ux_ehci_ed_next_anchor = ed; + } + + /* Memorize this ED in the local list. We do this operation now, otherwise + we would erase the previous list eds. */ + ed_list[current_list_entry] = ed; + } + + /* Shift the number of entries in the next list by 1 (i.e. divide by 2). */ + list_entries = list_entries>>1; + } + + /* Check the value of the ehci frame list entries. If 0, it was not initialized by the controller init function. */ + if (hcd_ehci -> ux_hcd_ehci_frame_list_size == 0) + + /* Value not initialized. Use default. */ + hcd_ehci -> ux_hcd_ehci_frame_list_size = UX_EHCI_FRAME_LIST_ENTRIES; + + /* The tree has been completed but the entries in the EHCI frame list are in the wrong order. + We need to swap each entry according to the EHCI specified entry order list so that we + have a fair interval frequency for each periodic ED. The primary eds are fetched from the + start list, translated into physical addresses and stored into the frame List. */ + for (current_list_entry = 0; current_list_entry < 32; current_list_entry++) + { + + ed = ed_start_list[_ux_system_host_hcd_periodic_tree_entries[current_list_entry]]; + *(hcd_ehci -> ux_hcd_ehci_frame_list+current_list_entry) = (UX_EHCI_ED *) _ux_utility_physical_address(ed); + } + + /* We still haven't set the type of each queue head in the list itself. Do that now. */ + for (current_list_entry = 0; current_list_entry < 32; current_list_entry++) + { + + lp.ed_ptr = hcd_ehci -> ux_hcd_ehci_frame_list[current_list_entry]; + lp.value |= UX_EHCI_QH_TYP_QH; + hcd_ehci -> ux_hcd_ehci_frame_list[current_list_entry] = lp.ed_ptr; + } + + /* Now the first 32 entries in the frame list have to be duplicated to fill the other entries in the frame list. + If the list is set to 32 entries, nothing is done here. */ + for (current_list_entry = 32; current_list_entry < hcd_ehci -> ux_hcd_ehci_frame_list_size; current_list_entry++) + hcd_ehci -> ux_hcd_ehci_frame_list[current_list_entry] = hcd_ehci -> ux_hcd_ehci_frame_list[current_list_entry & 0x1f]; + + /* Now each traffic list from entry consumes 1/32 periodic bandwidth. + * The poll entry layers depth low to high: + * 32ms, 16ms, 8ms, 4ms, 2ms, 1ms -- micro-frames + */ + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_poll_rate_entry_get.c b/common/usbx_host_controllers/src/ux_hcd_ehci_poll_rate_entry_get.c new file mode 100644 index 0000000..f47fba2 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_poll_rate_entry_get.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_poll_rate_entry_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function return a pointer to the first ED in the periodic tree */ +/* that start specific poll rate. */ +/* Note that when poll rate is longer, poll depth is smaller and */ +/* endpoint period interval is larger. */ +/* PollInterval Depth */ +/* 1 M */ +/* 2 M-1 */ +/* 4 M-2 */ +/* 8 M-3 */ +/* ... ... */ +/* N 0 */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* ed_list Pointer to ED list to scan */ +/* poll_depth Poll depth expected */ +/* */ +/* OUTPUT */ +/* */ +/* UX_EHCI_ED * Pointer to ED */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_EHCI_ED *_ux_hcd_ehci_poll_rate_entry_get(UX_HCD_EHCI *hcd_ehci, + UX_EHCI_ED *ed_list, ULONG poll_depth) +{ + + + UX_PARAMETER_NOT_USED(hcd_ehci); + + /* Scan the list of ED/iTD/siTDs from the poll rate lowest/interval longest + entry until appropriate poll rate node. + The depth index is the poll rate EHCI value and the first entry (anchor) + is pointed. */ + + /* Obtain next link pointer including Typ and T. */ + while(poll_depth --) + { + if (ed_list -> ux_ehci_ed_next_anchor == UX_NULL) + break; + ed_list = ed_list -> ux_ehci_ed_next_anchor; + } + + /* Return the list entry. */ + return(ed_list); +} diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_port_disable.c b/common/usbx_host_controllers/src/ux_hcd_ehci_port_disable.c new file mode 100644 index 0000000..e833f52 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_port_disable.c @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_port_disable PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will disable a specific port attached to the root */ +/* HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* port_index Port index to disable */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_register_read Read EHCI register */ +/* _ux_hcd_ehci_register_write Write EHCI register */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_port_disable(UX_HCD_EHCI *hcd_ehci, ULONG port_index) +{ + +ULONG ehci_register_port_status; + + + /* Check to see if this port is valid on this controller. */ + if (hcd_ehci -> ux_hcd_ehci_nb_root_hubs < port_index) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_INDEX_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_INDEX_UNKNOWN, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_PORT_INDEX_UNKNOWN); + } + + /* Read the port status for this port. */ + ehci_register_port_status = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_PORT_SC + port_index); + + /* Disable the port (CPE field). */ + ehci_register_port_status &= ~EHCI_HC_PS_PE; + + /* Write the status back. */ + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_PORT_SC + port_index, ehci_register_port_status); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_port_reset.c b/common/usbx_host_controllers/src/ux_hcd_ehci_port_reset.c new file mode 100644 index 0000000..ae4ae87 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_port_reset.c @@ -0,0 +1,240 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/* EHCI HCD extention for host mode select. */ +#ifndef UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET + +#if defined(K66) + +#define UX_EHCI_USBPHY_CTRL_K66 0x400A2000 +#define UX_EHCI_USBPHY_CTRL_SET_BIT1 ((*(volatile ULONG *)(UX_EHCI_USBPHY_CTRL_K66 + 0x34)) = 0x02) +#define UX_EHCI_USBPHY_CTRL_CLEAR_BIT1 ((*(volatile ULONG *)(UX_EHCI_USBPHY_CTRL_K66 + 0x38)) = 0x02) + +#define UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET(hcd_ehci, on_off) do \ +{ \ + if (on_off) \ + UX_EHCI_USBPHY_CTRL_SET_BIT1; \ + else \ + UX_EHCI_USBPHY_CTRL_CLEAR_BIT1; \ +} while(0) + +#elif defined(IMX6UL) || defined(MIMXRT) + +#if defined(IMX6UL) +#define UX_EHCI_USBPHY1 (0x020C9000) +#define UX_EHCI_USBPHY2 (0x020CA000) +#define UX_EHCI_BASE1 (0x02184100) +#define UX_EHCI_BASE2 (0x02184300) +#elif defined(MIMXRT) +#define UX_EHCI_USBPHY1 (0x400D9000u) +#define UX_EHCI_USBPHY2 (0x400DA000u) +#define UX_EHCI_BASE1 (0x402E0000u) +#define UX_EHCI_BASE2 (0x402E0200u) +#endif + +#define UX_EHCI_USBPHY_CTRL_SET_BIT1(base) ((*(volatile ULONG *) ( base + 0x34)) = 0x02) +#define UX_EHCI_USBPHY_CTRL_CLEAR_BIT1(base) ((*(volatile ULONG *) ( base + 0x38)) = 0x02) + +#define UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET(hcd_ehci, on_off) do \ +{ \ + ULONG base; \ + if ((ULONG)hcd_ehci -> ux_hcd_ehci_base == UX_EHCI_BASE1) \ + base = (UX_EHCI_USBPHY1); \ + else \ + base = (UX_EHCI_USBPHY1); \ + if (on_off) \ + UX_EHCI_USBPHY_CTRL_SET_BIT1(base); \ + else \ + UX_EHCI_USBPHY_CTRL_CLEAR_BIT1(base); \ +} while(0) + +#else +#define UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET(hcd_ehci, on_off) +#endif + +#endif /* ifndef UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET */ + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_port_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will reset a specific port attached to the root HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* port_index Port index to reset */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_register_read Read EHCI register */ +/* _ux_hcd_ehci_register_write Write EHCI register */ +/* _ux_utility_delay_ms Delay */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_port_reset(UX_HCD_EHCI *hcd_ehci, ULONG port_index) +{ + +ULONG ehci_register_port_status; +INT i; + + + /* Check to see if this port is valid on this controller. */ + if (hcd_ehci -> ux_hcd_ehci_nb_root_hubs < port_index) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_INDEX_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_INDEX_UNKNOWN, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_PORT_INDEX_UNKNOWN); + } + + /* Ensure that the downstream port has a device attached. It is unnatural to perform + a port reset if there is no device. */ + ehci_register_port_status = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_PORT_SC + port_index); + + /* Check Device Connection Status. */ + if ((ehci_register_port_status & EHCI_HC_PS_CCS) == 0) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_NO_DEVICE_CONNECTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_NO_DEVICE_CONNECTED, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_NO_DEVICE_CONNECTED); + } + + /* Check for the speed of the device. If low speed, we need to send the connection signal + to the companion chip. Unless we are on a controller with a built-in TT. */ + if ((ehci_register_port_status & EHCI_HC_PS_SPEED_MASK) != EHCI_HC_PS_SPEED_LOW || (hcd_ehci -> ux_hcd_ehci_embedded_tt == UX_TRUE)) + { + + for (i = 0; ; i ++) + { + + /* Before reset, phy does not know the speed. */ + UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET(hcd_ehci, UX_FALSE); + + /* The device may be high speed or full speed, we try to reset the port for some time + and see if the port is enabled by the host controller. */ + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_PORT_SC + port_index, (ehci_register_port_status | EHCI_HC_PS_PR)); + + /* Wait until the port has been reset. */ + _ux_utility_delay_ms(EHCI_HC_RH_RESET_DELAY ); + + /* Now turn off the port reset. */ + ehci_register_port_status = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_PORT_SC + port_index); + if (ehci_register_port_status & EHCI_HC_PS_PR) + { + + ehci_register_port_status &= ~EHCI_HC_PS_PR; + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_PORT_SC + port_index, ehci_register_port_status); + + /* According to the USB 2.0 spec, the controller may take 2ms to reset the port bit from 1 to 0 after + we write a 0. Wait until the port reset bit has been turned off completely. */ + _ux_utility_delay_ms(EHCI_HC_RH_RESET_SETTLE_DELAY); + } + + /* Now check port speed. */ + ehci_register_port_status = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_PORT_SC + port_index); + if (hcd_ehci -> ux_hcd_ehci_embedded_tt && + (ehci_register_port_status & EHCI_HC_PS_EMBEDDED_TT_SPEED_MASK) == EHCI_HC_PS_EMBEDDED_TT_SPEED_HIGH) + break; + + /* Seems we need to set the Port to a Suspend state before forcing the reset. Otherwise some devices fail the + HS detection handshake. */ + if (i == 0) + { + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_PORT_SC + port_index, (ehci_register_port_status | EHCI_HC_PS_SUSPEND)); + _ux_utility_delay_ms(UX_HIGH_SPEED_DETECTION_HANDSHAKE_SUSPEND_WAIT); + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_PORT_SC + port_index, (ehci_register_port_status & ~EHCI_HC_PS_SUSPEND)); + } + else + break; + } + + /* Now we can read the port enable bit. */ + ehci_register_port_status = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_PORT_SC + port_index); + if ((ehci_register_port_status & EHCI_HC_PS_PE) != 0) + { + + /* After reset, adjust phy speed. */ + UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET(hcd_ehci, UX_TRUE); + return(UX_SUCCESS); + } + } + + /* We come here when the device is either low speed or full speed. In this case, we release + the ownership of the port to the companion chip. */ + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_PORT_SC + port_index, (ehci_register_port_status | EHCI_HC_PS_PO)); + + /* Delay. */ + _ux_utility_delay_ms(EHCI_HC_RH_RESET_DELAY); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_RESET_FAILED, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_RESET_FAILED); + + /* When the root HUB sees an error message, it will give up on this device and the companion chip root HUB + will pick up the insertion signal again and reawake the root HUB driver. */ + return(UX_PORT_RESET_FAILED); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_port_resume.c b/common/usbx_host_controllers/src/ux_hcd_ehci_port_resume.c new file mode 100644 index 0000000..25e33e7 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_port_resume.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_port_resume PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will resume a specific port attached to the root HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* port_index Port index to resume */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_port_resume(UX_HCD_EHCI *hcd_ehci, UINT port_index) +{ + + UX_PARAMETER_NOT_USED(hcd_ehci); + UX_PARAMETER_NOT_USED(port_index); + + /* Not supported, return to caller. */ + return(UX_FUNCTION_NOT_SUPPORTED); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_port_status_get.c b/common/usbx_host_controllers/src/ux_hcd_ehci_port_status_get.c new file mode 100644 index 0000000..1ecb182 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_port_status_get.c @@ -0,0 +1,252 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/* EHCI HCD extention for host mode select. */ +#ifndef UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET + +#if defined(K66) + +#define UX_EHCI_USBPHY_CTRL_K66 0x400A2000 +#define UX_EHCI_USBPHY_CTRL_SET_BIT1 ((*(volatile ULONG *)(UX_EHCI_USBPHY_CTRL_K66 + 0x34)) = 0x02) +#define UX_EHCI_USBPHY_CTRL_CLEAR_BIT1 ((*(volatile ULONG *)(UX_EHCI_USBPHY_CTRL_K66 + 0x38)) = 0x02) + +#define UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET(hcd_ehci, on_off) do \ +{ \ + if (on_off) \ + UX_EHCI_USBPHY_CTRL_SET_BIT1; \ + else \ + UX_EHCI_USBPHY_CTRL_CLEAR_BIT1; \ +} while(0) + +#elif defined(IMX6UL) || defined(MIMXRT) + +#if defined(IMX6UL) +#define UX_EHCI_USBPHY1 (0x020C9000) +#define UX_EHCI_USBPHY2 (0x020CA000) +#define UX_EHCI_BASE1 (0x02184100) +#define UX_EHCI_BASE2 (0x02184300) +#elif defined(MIMXRT) +#define UX_EHCI_USBPHY1 (0x400D9000u) +#define UX_EHCI_USBPHY2 (0x400DA000u) +#define UX_EHCI_BASE1 (0x402E0000u) +#define UX_EHCI_BASE2 (0x402E0200u) +#endif + +#define UX_EHCI_USBPHY_CTRL_SET_BIT1(base) ((*(volatile ULONG *) ( base + 0x34)) = 0x02) +#define UX_EHCI_USBPHY_CTRL_CLEAR_BIT1(base) ((*(volatile ULONG *) ( base + 0x38)) = 0x02) + +#define UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET(hcd_ehci, on_off) do \ +{ \ + ULONG base; \ + if ((ULONG)hcd_ehci -> ux_hcd_ehci_base == UX_EHCI_BASE1) \ + base = (UX_EHCI_USBPHY1); \ + else \ + base = (UX_EHCI_USBPHY1); \ + if (on_off) \ + UX_EHCI_USBPHY_CTRL_SET_BIT1(base); \ + else \ + UX_EHCI_USBPHY_CTRL_CLEAR_BIT1(base); \ +} while(0) + +#else +#define UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET(hcd_ehci, on_off) +#endif + +#endif /* ifndef UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET */ + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_port_status_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will return the status for each port attached to the */ +/* root HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* port_index Port index to get status for */ +/* */ +/* OUTPUT */ +/* */ +/* Port Status */ +/* */ +/* Status of the root hub port with the following format: */ +/* */ +/* bit 0 device connection status */ +/* if 0 : no device connected */ +/* if 1 : device connected to the port */ +/* bit 1 port enable status */ +/* if 0 : port disabled */ +/* if 1 : port enabled */ +/* bit 2 port suspend status */ +/* if 0 : port is not suspended */ +/* if 1 : port is suspended */ +/* bit 3 port overcurrent status */ +/* if 0 : port has no overcurrent condition */ +/* if 1 : port has overcurrent condition */ +/* bit 4 port reset status */ +/* if 0 : port is not in reset */ +/* if 1 : port is in reset */ +/* bit 5 port power status */ +/* if 0 : port power is off */ +/* if 1 : port power is on */ +/* bit 6-7 device attached speed */ +/* if 00 : low speed device attached */ +/* if 01 : full speed device attached */ +/* if 10 : high speed device attached */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_register_read Read EHCI register */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_hcd_ehci_port_status_get(UX_HCD_EHCI *hcd_ehci, ULONG port_index) +{ + +ULONG ehci_register_port_status; +ULONG port_status; + + + /* Check to see if this port is valid on this controller. */ + if (hcd_ehci -> ux_hcd_ehci_nb_root_hubs < port_index) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_INDEX_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_INDEX_UNKNOWN, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_PORT_INDEX_UNKNOWN); + } + + /* The port is valid, build the status mask for this port. This function + returns a controller agnostic bit field. */ + port_status = 0; + ehci_register_port_status = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_PORT_SC + port_index); + + /* Device Connection Status. */ + if (ehci_register_port_status & EHCI_HC_PS_CCS) + port_status |= UX_PS_CCS; + else + { + + /* When disconnected PHY does not know speed. */ + UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET(hcd_ehci, UX_FALSE); + } + + /* Port Enable Status. */ + if (ehci_register_port_status & EHCI_HC_PS_PE) + port_status |= UX_PS_PES; + + /* Port Suspend Status. */ + if (ehci_register_port_status & EHCI_HC_PS_SUSPEND) + { + port_status |= UX_PS_PSS; + + /* When suspend put PHY in normal to avoid wrong disconnect status. */ + UX_HCD_EHCI_EXT_USBPHY_HIGHSPEED_MODE_SET(hcd_ehci, UX_FALSE); + } + + /* Port Overcurrent Status. */ + if (ehci_register_port_status & EHCI_HC_PS_OCC) + port_status |= UX_PS_POCI; + + /* Port Reset Status. */ + if (ehci_register_port_status & EHCI_HC_PS_PR) + port_status |= UX_PS_PRS; + + /* Port Power Status. */ + if (ehci_register_port_status & EHCI_HC_PS_PP) + port_status |= UX_PS_PPS; + + /* Port Device Attached speed. This field is valid only if the CCS bit is active. + Only EHCI high speed devices are meaningful in a regular EHCI controller. + In embedded EHCI with built-in TTs some bits reflect the true speed of + the device behind the TT. */ + if (ehci_register_port_status & EHCI_HC_PS_CCS) + { + /* Check for EHCI with embedded TT. */ + if (hcd_ehci -> ux_hcd_ehci_embedded_tt == UX_TRUE) + { + + /* Isolate speed from the non EHCI compliant POTSC bits. */ + switch (ehci_register_port_status & EHCI_HC_PS_EMBEDDED_TT_SPEED_MASK) + { + + case EHCI_HC_PS_EMBEDDED_TT_SPEED_FULL : + + /* Full speed. */ + port_status |= UX_PS_DS_FS; + break; + + case EHCI_HC_PS_EMBEDDED_TT_SPEED_LOW : + + /* Low speed. */ + port_status |= UX_PS_DS_LS; + break; + + case EHCI_HC_PS_EMBEDDED_TT_SPEED_HIGH : + + /* High speed. */ + port_status |= UX_PS_DS_HS; + break; + + } + } + else + + /* No embedded TT. Fall back to default HS. */ + port_status |= UX_PS_DS_HS; + } + + /* Return port status. */ + return(port_status); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_port_suspend.c b/common/usbx_host_controllers/src/ux_hcd_ehci_port_suspend.c new file mode 100644 index 0000000..224c8ea --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_port_suspend.c @@ -0,0 +1,107 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_port_suspend PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will suspend a specific port attached to the root */ +/* HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* port_index Port index to suspend */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_port_suspend(UX_HCD_EHCI *hcd_ehci, ULONG port_index) +{ +ULONG ehci_register_port_status; + + /* Check to see if this port is valid on this controller. */ + if (hcd_ehci -> ux_hcd_ehci_nb_root_hubs < port_index) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_INDEX_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_INDEX_UNKNOWN, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_PORT_INDEX_UNKNOWN); + } + + /* Ensure that the downstream port has a device attached. If not, ignore the request. */ + ehci_register_port_status = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_PORT_SC + port_index); + + /* Check Device Connection Status. */ + if ((ehci_register_port_status & EHCI_HC_PS_CCS) == 0) + + /* Nothing on the downstream port. */ + return(UX_NO_DEVICE_CONNECTED); + + /* Set Suspend. */ + ehci_register_port_status |= EHCI_HC_PS_SUSPEND; + + /* Update the port status. */ + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_PORT_SC + port_index, ehci_register_port_status); + + /* Not supported, return error. */ + return(UX_FUNCTION_NOT_SUPPORTED); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_power_down_port.c b/common/usbx_host_controllers/src/ux_hcd_ehci_power_down_port.c new file mode 100644 index 0000000..60e3b52 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_power_down_port.c @@ -0,0 +1,81 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_power_down_port PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will power down a specific port attached to the root */ +/* HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* port_index Port index to power down */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_power_down_port(UX_HCD_EHCI *hcd_ehci, ULONG port_index) +{ + + UX_PARAMETER_NOT_USED(hcd_ehci); + UX_PARAMETER_NOT_USED(port_index); + + /* Not supported, return error. */ + return(UX_FUNCTION_NOT_SUPPORTED); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_power_on_port.c b/common/usbx_host_controllers/src/ux_hcd_ehci_power_on_port.c new file mode 100644 index 0000000..2c3c70b --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_power_on_port.c @@ -0,0 +1,80 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_power_on_port PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will power a specific port attached to the root HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* port_index Port index to power */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_power_on_port(UX_HCD_EHCI *hcd_ehci, ULONG port_index) +{ + + UX_PARAMETER_NOT_USED(hcd_ehci); + UX_PARAMETER_NOT_USED(port_index); + + /* Not supported, return error code. */ + return(UX_FUNCTION_NOT_SUPPORTED); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_power_root_hubs.c b/common/usbx_host_controllers/src/ux_hcd_ehci_power_root_hubs.c new file mode 100644 index 0000000..0499c7a --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_power_root_hubs.c @@ -0,0 +1,105 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_power_root_hubs PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function powers individually or in gang mode the root HUBs */ +/* attached to the EHCI controller. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_register_read Read EHCI register */ +/* _ux_hcd_ehci_register_write Write EHCI register */ +/* _ux_utility_delay_ms Delay */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ehci_power_root_hubs(UX_HCD_EHCI *hcd_ehci) +{ + +ULONG ehci_register; +UINT port_index; + + + /* Read the control PPC field. If the PPC field is set, the controller has + implemented port power. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCCR_HCS_PARAMS); + + if (ehci_register & EHCI_HC_RH_PPC) + { + + /* We have power management in this controller. Apply power to each port. */ + for (port_index = 0; port_index < hcd_ehci -> ux_hcd_ehci_nb_root_hubs; port_index++) + { + + /* Read register first to preserve existing settings. */ + ehci_register = _ux_hcd_ehci_register_read(hcd_ehci, EHCI_HCOR_PORT_SC + port_index); + + /* Apply power to a port. */ + _ux_hcd_ehci_register_write(hcd_ehci, EHCI_HCOR_PORT_SC + port_index, ehci_register | EHCI_HC_PS_PP); + } + } + + /* The EHCI needs some time for the power to be stable. */ + _ux_utility_delay_ms(EHCI_HC_RH_POWER_STABLE_DELAY); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_register_read.c b/common/usbx_host_controllers/src/ux_hcd_ehci_register_read.c new file mode 100644 index 0000000..1a78a98 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_register_read.c @@ -0,0 +1,78 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_register_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads a register from the EHCI memory mapped */ +/* registers. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* ehci_register EHCI register to read */ +/* */ +/* OUTPUT */ +/* */ +/* EHCI Register Value */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_hcd_ehci_register_read(UX_HCD_EHCI *hcd_ehci, ULONG ehci_register) +{ + + /* Return value of EHCI register. */ + return(*(hcd_ehci -> ux_hcd_ehci_base + ehci_register)); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_register_write.c b/common/usbx_host_controllers/src/ux_hcd_ehci_register_write.c new file mode 100644 index 0000000..9b6ccb4 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_register_write.c @@ -0,0 +1,81 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_register_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a register to the EHCI space. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* ehci_register EHCI register to write */ +/* value Value to write */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ehci_register_write(UX_HCD_EHCI *hcd_ehci, ULONG ehci_register, ULONG value) +{ + + /* Write to the specified EHCI register. */ + *(hcd_ehci -> ux_hcd_ehci_base + ehci_register) = value; + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_regular_td_obtain.c b/common/usbx_host_controllers/src/ux_hcd_ehci_regular_td_obtain.c new file mode 100644 index 0000000..705f66b --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_regular_td_obtain.c @@ -0,0 +1,122 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_regular_td_obtain PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains a free TD from the regular TD list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* UX_EHCI_TD * Pointer to TD */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_set Set memory block */ +/* _ux_utility_mutex_on Get protection mutex */ +/* _ux_utility_mutex_off Release protection mutex */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_EHCI_TD *_ux_hcd_ehci_regular_td_obtain(UX_HCD_EHCI *hcd_ehci) +{ + +UX_EHCI_TD *td; +ULONG td_index; +ULONG td_element; + + + /* Get the mutex as this is a critical section. */ + _ux_utility_mutex_on(&_ux_system -> ux_system_mutex); + + /* Start the search from the beginning of the list. */ + td = hcd_ehci -> ux_hcd_ehci_td_list; + for (td_index = 0; td_index < _ux_system_host -> ux_system_host_max_td; td_index++) + { + + /* Check the TD status, a free TD is marked with the USED flag. */ + if (td -> ux_ehci_td_status == UX_UNUSED) + { + + /* The TD may have been used, so we reset all fields. */ + _ux_utility_memory_set(td, 0, sizeof(UX_EHCI_TD)); + + /* This TD is now marked as USED. */ + td -> ux_ehci_td_status = UX_USED; + + /* Initialize the link pointer and alternate TD fields. */ + td_element = UX_EHCI_TD_T; + td -> ux_ehci_td_link_pointer = (UX_EHCI_TD *) td_element; + td -> ux_ehci_td_alternate_link_pointer = (UX_EHCI_TD *) td_element; + + /* Release the protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* Success, return TD pointer. */ + return(td); + } + + /* Look at next TD. */ + td++; + } + + /* There is no available TD in the TD list. */ + + /* Release protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* Error, return a null. */ + return(UX_NULL); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_request_bulk_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ehci_request_bulk_transfer.c new file mode 100644 index 0000000..9e62567 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_request_bulk_transfer.c @@ -0,0 +1,168 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_request_bulk_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a bulk transfer request. A bulk transfer */ +/* can be larger than the size of the EHCI buffer so it may be */ +/* required to chain multiple tds to accommodate this request. A bulk */ +/* transfer is non blocking, so we return before the request is */ +/* completed. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_request_transfer_add Add transfer to ED */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_request_bulk_transfer(UX_HCD_EHCI *hcd_ehci, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_EHCI_ED *ed; +ULONG transfer_request_payload_length; +ULONG bulk_packet_payload_length; +UCHAR * data_pointer; +ULONG pid; +ULONG td_component; +UINT status; +ULONG zlp_flag; + + + /* Get the pointer to the Endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* Now get the physical ED attached to this endpoint. */ + ed = endpoint -> ux_endpoint_ed; + + /* The overlay parameters should be reset now. */ + ed -> ux_ehci_ed_current_td = UX_NULL; + ed -> ux_ehci_ed_queue_element = (UX_EHCI_TD *)UX_EHCI_TD_T; + ed -> ux_ehci_ed_alternate_td = (UX_EHCI_TD *)UX_EHCI_TD_T; + ed -> ux_ehci_ed_state &= UX_EHCI_QH_TOGGLE; + ed -> ux_ehci_ed_bp0 = UX_NULL; + ed -> ux_ehci_ed_bp0 = UX_NULL; + ed -> ux_ehci_ed_bp1 = UX_NULL; + ed -> ux_ehci_ed_bp2 = UX_NULL; + ed -> ux_ehci_ed_bp3 = UX_NULL; + ed -> ux_ehci_ed_bp4 = UX_NULL; + + /* It may take more than one TD if the transfer_request length is more than the + maximum length for an EHCI TD (this is irrelevant of the MaxPacketSize value + in the endpoint descriptor). EHCI data payload has a maximum size of 16K. */ + transfer_request_payload_length = transfer_request -> ux_transfer_request_requested_length; + data_pointer = transfer_request -> ux_transfer_request_data_pointer; + + /* Check for ZLP condition. */ + if (transfer_request_payload_length == 0) + + /* We have a zlp condition. */ + zlp_flag = UX_TRUE; + else + + /* We do not have a zlp. */ + zlp_flag = UX_FALSE; + + /* Build all necessary TDs. */ + while ((transfer_request_payload_length != 0) || zlp_flag == UX_TRUE) + { + + /* Reset ZLP now. */ + zlp_flag = UX_FALSE; + + /* Check if we are exceeding the max payload. */ + if (transfer_request_payload_length > UX_EHCI_MAX_PAYLOAD) + bulk_packet_payload_length = UX_EHCI_MAX_PAYLOAD; + else + bulk_packet_payload_length = transfer_request_payload_length; + + /* Add this transfer request to the ED. */ + if ((transfer_request -> ux_transfer_request_type&UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + pid = UX_EHCI_PID_IN; + else + pid = UX_EHCI_PID_OUT; + + status = _ux_hcd_ehci_request_transfer_add(hcd_ehci, ed, 0, pid, 0, + data_pointer, bulk_packet_payload_length, transfer_request); + + if (status != UX_SUCCESS) + return(status); + + /* Adjust the data payload length and the data payload pointer. */ + transfer_request_payload_length -= bulk_packet_payload_length; + data_pointer += bulk_packet_payload_length; + } + + /* Set the IOC bit in the last TD. */ + ed -> ux_ehci_ed_last_td -> ux_ehci_td_control |= UX_EHCI_TD_IOC; + + /* Ensure the IOC bit is set before activating the TD. This is necessary + for some processors that perform writes out of order as an optimization. */ + UX_DATA_MEMORY_BARRIER + + /* Activate the first TD linked to the ED. */ + td_component = (ULONG) ed -> ux_ehci_ed_queue_element; + td_component &= ~UX_EHCI_TD_T; + ed -> ux_ehci_ed_queue_element = (UX_EHCI_TD *) td_component; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_request_control_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ehci_request_control_transfer.c new file mode 100644 index 0000000..bdc53da --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_request_control_transfer.c @@ -0,0 +1,234 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_request_control_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a control transfer from a transfer request. */ +/* The USB control transfer is in 3 phases (setup, data, status). */ +/* This function will chain all phases of the control sequence before */ +/* setting the EHCI endpoint as a candidate for transfer. */ +/* */ +/* The max aggregated size of a data payload in EHCI is 16K. We are */ +/* assuming that this size will be sufficient to contain the control */ +/* packet. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_ed_clean Clean TDs */ +/* _ux_hcd_ehci_request_transfer_add Add transfer to ED */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_short_put Write a 16-bit value */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_request_control_transfer(UX_HCD_EHCI *hcd_ehci, UX_TRANSFER *transfer_request) +{ + +UX_DEVICE *device; +UX_ENDPOINT *endpoint; +UCHAR * setup_request; +UX_EHCI_ED *ed; +ULONG td_component; +UINT status; +UINT pid; + + + /* Get the pointer to the Endpoint and to the device. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + device = endpoint -> ux_endpoint_device; + + /* Now get the physical ED attached to this endpoint. */ + ed = endpoint -> ux_endpoint_ed; + + /* Build the SETUP packet (phase 1 of the control transfer). */ + setup_request = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_SETUP_SIZE); + if (setup_request == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + *setup_request = transfer_request -> ux_transfer_request_function; + *(setup_request + UX_SETUP_REQUEST_TYPE) = transfer_request -> ux_transfer_request_type; + *(setup_request + UX_SETUP_REQUEST) = transfer_request -> ux_transfer_request_function; + _ux_utility_short_put(setup_request + UX_SETUP_VALUE, transfer_request -> ux_transfer_request_value); + _ux_utility_short_put(setup_request + UX_SETUP_INDEX, transfer_request -> ux_transfer_request_index); + _ux_utility_short_put(setup_request + UX_SETUP_LENGTH, (USHORT) transfer_request -> ux_transfer_request_requested_length); + + /* Reset the last TD pointer since it is the first time we hook a transaction. */ + ed -> ux_ehci_ed_last_td = UX_NULL; + + /* Set the ED address and MPS values since they may have changed from 0 to x + The ED direction will be set from the TD. */ + ed -> ux_ehci_ed_cap0 |= (endpoint -> ux_endpoint_descriptor.bEndpointAddress & ~UX_ENDPOINT_DIRECTION) << UX_EHCI_QH_ED_AD_LOC; + + /* Set the endpoint address (this should have changed after address setting). */ + ed -> ux_ehci_ed_cap0 |= device -> ux_device_address; + + /* Set the default MPS Capability info in the ED. */ + ed -> ux_ehci_ed_cap0 &= ~UX_EHCI_QH_MPS_MASK; + ed -> ux_ehci_ed_cap0 |= endpoint -> ux_endpoint_descriptor.wMaxPacketSize << UX_EHCI_QH_MPS_LOC; + + /* On Control transfers, the toggle is set in the TD, not the QH. */ + ed -> ux_ehci_ed_cap0 |= UX_EHCI_QH_DTC; + + /* The overlay parameters should be reset now. */ + ed -> ux_ehci_ed_current_td = UX_NULL; + ed -> ux_ehci_ed_queue_element = (UX_EHCI_TD *) UX_EHCI_TD_T; + ed -> ux_ehci_ed_alternate_td = (UX_EHCI_TD *) UX_EHCI_TD_T; + ed -> ux_ehci_ed_state &= UX_EHCI_QH_TOGGLE; + ed -> ux_ehci_ed_bp0 = UX_NULL; + ed -> ux_ehci_ed_bp1 = UX_NULL; + ed -> ux_ehci_ed_bp2 = UX_NULL; + ed -> ux_ehci_ed_bp3 = UX_NULL; + ed -> ux_ehci_ed_bp4 = UX_NULL; + + /* Build and hook the setup phase to the ED. */ + status = _ux_hcd_ehci_request_transfer_add(hcd_ehci, ed, UX_EHCI_TD_SETUP_PHASE, UX_EHCI_PID_SETUP, UX_EHCI_TOGGLE_0, + setup_request, UX_SETUP_SIZE, transfer_request); + if (status != UX_SUCCESS) + { + + /* We need to clean the tds attached if any. */ + _ux_hcd_ehci_ed_clean(ed); + return(status); + } + + /* Test if data phase required, if so decide the PID to use and build/hook it to the ED. */ + if (transfer_request -> ux_transfer_request_requested_length != 0) + { + + if ((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + + pid = UX_EHCI_PID_IN; + else + + pid = UX_EHCI_PID_OUT; + + status = _ux_hcd_ehci_request_transfer_add(hcd_ehci, ed, UX_EHCI_TD_DATA_PHASE, pid, UX_EHCI_TOGGLE_1, + transfer_request -> ux_transfer_request_data_pointer, + transfer_request -> ux_transfer_request_requested_length, + transfer_request); + if (status != UX_SUCCESS) + { + + /* We need to clean the tds attached if any. */ + _ux_hcd_ehci_ed_clean(ed); + return(status); + } + } + + /* Program the status phase. the PID is the opposite of the data phase. */ + if ((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + pid = UX_EHCI_PID_OUT; + else + pid = UX_EHCI_PID_IN; + + status = _ux_hcd_ehci_request_transfer_add(hcd_ehci, ed, UX_EHCI_TD_STATUS_PHASE, pid, + UX_EHCI_TOGGLE_1, UX_NULL, 0, transfer_request); + + if (status != UX_SUCCESS) + { + + /* We need to clean the tds attached if any. */ + _ux_hcd_ehci_ed_clean(ed); + return(status); + } + + /* Set the IOC bit in the last TD. */ + ed -> ux_ehci_ed_last_td -> ux_ehci_td_control |= UX_EHCI_TD_IOC; + + /* Ensure the IOC bit is set before activating the TD. This is necessary + for some processors that perform writes out of order as an optimization. */ + UX_DATA_MEMORY_BARRIER + + /* Activate the first TD linked to the ED. */ + td_component = (ULONG) ed -> ux_ehci_ed_queue_element; + td_component &= ~UX_EHCI_TD_T; + ed -> ux_ehci_ed_queue_element = (UX_EHCI_TD *) td_component; + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_CONTROL_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* There was an error, return to the caller. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + } + + /* Free the resources. */ + _ux_utility_memory_free(setup_request); + + /* Return completion status. */ + return(transfer_request -> ux_transfer_request_completion_code); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_request_interrupt_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ehci_request_interrupt_transfer.c new file mode 100644 index 0000000..740104f --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_request_interrupt_transfer.c @@ -0,0 +1,134 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_request_interrupt_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs an interrupt transfer request. An interrupt */ +/* transfer can only be as large as the MaxpacketField in the */ +/* endpoint descriptor. This was verified at the upper layer and does */ +/* not need to be reverified here. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_request_transfer_add Add transfer to ED */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_request_interrupt_transfer(UX_HCD_EHCI *hcd_ehci, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_EHCI_ED *ed; +ULONG pid; +ULONG td_component; +UINT status; + + + /* Get the pointer to the endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* Now get the physical ED attached to this endpoint. */ + ed = endpoint -> ux_endpoint_ed; + + /* The overlay parameters should be reset now. */ + ed -> ux_ehci_ed_current_td = UX_NULL; + ed -> ux_ehci_ed_queue_element = (UX_EHCI_TD *) UX_EHCI_TD_T; + ed -> ux_ehci_ed_alternate_td = (UX_EHCI_TD *) UX_EHCI_QH_T; + ed -> ux_ehci_ed_state &= UX_EHCI_QH_TOGGLE; + ed -> ux_ehci_ed_bp0 = UX_NULL; + ed -> ux_ehci_ed_bp1 = UX_NULL; + ed -> ux_ehci_ed_bp2 = UX_NULL; + ed -> ux_ehci_ed_bp3 = UX_NULL; + ed -> ux_ehci_ed_bp4 = UX_NULL; + + /* Get the correct PID for this transfer. */ + if ((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + pid = UX_EHCI_PID_IN; + else + pid = UX_EHCI_PID_OUT; + + /* Add this transfer request to the ED. */ + status = _ux_hcd_ehci_request_transfer_add(hcd_ehci, ed, 0, pid, 0, + transfer_request -> ux_transfer_request_data_pointer, + transfer_request -> ux_transfer_request_requested_length, + transfer_request); + + /* Ensure we got the TD allocated properly. */ + if (status == UX_SUCCESS) + { + + /* Set the IOC bit in the last TD. */ + ed -> ux_ehci_ed_last_td -> ux_ehci_td_control |= UX_EHCI_TD_IOC; + + /* Ensure the IOC bit is set before activating the TD. This is necessary + for some processors that perform writes out of order as an optimization. */ + UX_DATA_MEMORY_BARRIER + + /* Activate the first TD linked to the ED. */ + td_component = (ULONG) ed -> ux_ehci_ed_queue_element; + td_component &= ~UX_EHCI_TD_T; + ed -> ux_ehci_ed_queue_element = (UX_EHCI_TD *) td_component; + + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_request_isochronous_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ehci_request_isochronous_transfer.c new file mode 100644 index 0000000..938cc5c --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_request_isochronous_transfer.c @@ -0,0 +1,178 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_request_isochronous_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs an isochronous transfer request (list). */ +/* */ +/* Note: the request max length is endpoint max packet size, multiple */ +/* endpoint max number of transactions. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* transfer_request Pointer to transfer request. */ +/* If next transfer request is */ +/* valid the whole request list */ +/* is added, until next transfer */ +/* request being NULL. If next */ +/* next transfer request is not */ +/* valid (being NULL) single */ +/* transfer request is added. */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_mutex_on Get mutex */ +/* _ux_utility_mutex_off Put mutex */ +/* _ux_utility_semaphore_put Put semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_request_isochronous_transfer(UX_HCD_EHCI *hcd_ehci, UX_TRANSFER *transfer_request) +{ +#if UX_MAX_ISO_TD == 0 + + UX_PARAMETER_NOT_USED(hcd_ehci); + UX_PARAMETER_NOT_USED(transfer_request); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Not supported yet - return error. */ + return(UX_FUNCTION_NOT_SUPPORTED); +#else + +UX_ENDPOINT *endpoint; +UX_EHCI_PERIODIC_LINK_POINTER lp; +UX_EHCI_HSISO_ED *ied; +UX_TRANSFER **head; +UX_TRANSFER **tail; +UX_TRANSFER **first_new; +UX_TRANSFER *request_list; +UCHAR start = UX_FALSE; + + + /* Get the pointer to the endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* Now get the physical iTD/siTD attached to this endpoint. */ + lp.ed_ptr = endpoint -> ux_endpoint_ed; + + /* Lock the periodic list to update. */ + _ux_utility_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + + /* Append the request to iTD/siTD request list tail. */ +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + head = &lp.sitd_ptr -> ux_ehci_fsiso_td_transfer_head; + else +#endif + { + + /* Get pointer of ED. */ + ied = lp.itd_ptr -> ux_ehci_hsiso_td_ed; + + /* Get pointer locations. */ + head = &ied -> ux_ehci_hsiso_ed_transfer_head; + tail = &ied -> ux_ehci_hsiso_ed_transfer_tail; + first_new = &ied -> ux_ehci_hsiso_ed_transfer_first_new; + + /* If there is no transfer, start. */ + if (ied -> ux_ehci_hsiso_ed_frstart == 0xFF) + { + ied -> ux_ehci_hsiso_ed_frstart = 0xFE; + start = UX_TRUE; + } + } + + request_list = (*head); + if (request_list == UX_NULL) + { + + /* Link to head. */ + (*head) = transfer_request; + (*tail) = transfer_request; + (*first_new) = transfer_request; + } + else + { + + /* Link to tail of the list. */ + (*tail) -> ux_transfer_request_next_transfer_request = transfer_request; + + /* In case there is nothing to load, set new ones. */ + if (*first_new == UX_NULL) + *first_new = transfer_request; + } + + /* Move tail until it's real last one. */ + while((*tail) -> ux_transfer_request_next_transfer_request != UX_NULL) + (*tail) = ((*tail) -> ux_transfer_request_next_transfer_request); + + /* Release the periodic table. */ + _ux_utility_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + + /* Simulate iTD/siTD done to start - HCD signal. */ + if (start) + { + hcd_ehci -> ux_hcd_ehci_hcd_owner -> ux_hcd_thread_signal ++; + _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + } + + /* Return completion status. */ + return(UX_SUCCESS); +#endif +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_request_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ehci_request_transfer.c new file mode 100644 index 0000000..11aa77d --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_request_transfer.c @@ -0,0 +1,126 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_request_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the handler for all the transactions on the USB. */ +/* The transfer request passed as parameter contains the endpoint and */ +/* the device descriptors in addition to the type of transaction de */ +/* be executed. */ +/* */ +/* This function routes the transfer_request to according to the type */ +/* of transfer to be executed. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_request_control_transfer Start control transfer */ +/* _ux_hcd_ehci_request_bulk_transfer Start bulk transfer */ +/* _ux_hcd_ehci_request_interrupt_transfer Start interrupt transfer */ +/* _ux_hcd_ehci_request_isochronous_transfer Start iso transfer */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_request_transfer(UX_HCD_EHCI *hcd_ehci, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UINT status; + + + /* Get the pointer to the Endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* We reset the actual length field of the transfer request as a safety measure. */ + transfer_request -> ux_transfer_request_actual_length = 0; + + /* Isolate the endpoint type and route the transfer request. */ + switch ((endpoint -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + + status = _ux_hcd_ehci_request_control_transfer(hcd_ehci, transfer_request); + break; + + + case UX_BULK_ENDPOINT: + + status = _ux_hcd_ehci_request_bulk_transfer(hcd_ehci, transfer_request); + break; + + + case UX_INTERRUPT_ENDPOINT: + + status = _ux_hcd_ehci_request_interrupt_transfer(hcd_ehci, transfer_request); + break; + + + case UX_ISOCHRONOUS_ENDPOINT: + + status = _ux_hcd_ehci_request_isochronous_transfer(hcd_ehci, transfer_request); + break; + + } + + /* Note that it is physically impossible to have a wrong endpoint type here + so no error checking. */ + return(status); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_request_transfer_add.c b/common/usbx_host_controllers/src/ux_hcd_ehci_request_transfer_add.c new file mode 100644 index 0000000..599fdc5 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_request_transfer_add.c @@ -0,0 +1,156 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_request_transfer_add PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds a component of a transfer to an existing ED. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* ed Pointer to the ED */ +/* phase Phase (for control transfers) */ +/* pid PID to be used with this */ +/* request (SETUP,IN,OUT) */ +/* toggle Toggle value 0 or 1 */ +/* buffer_address Buffer address for transfer */ +/* buffer_length Buffer length */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ehci_regular_td_obtain Obtain regular TD */ +/* _ux_utility_physical_address Get physical address */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_request_transfer_add(UX_HCD_EHCI *hcd_ehci, UX_EHCI_ED *ed, ULONG phase, ULONG pid, + ULONG toggle, UCHAR * buffer_address, ULONG buffer_length, UX_TRANSFER *transfer_request) +{ + +UX_EHCI_TD *last_td; +UX_EHCI_TD *td; +UX_EHCI_LINK_POINTER lp; +UX_EHCI_POINTER bp; + + + /* Obtain a TD for this transaction. */ + td = _ux_hcd_ehci_regular_td_obtain(hcd_ehci); + if (td == UX_NULL) + return(UX_NO_TD_AVAILABLE); + + /* Store the transfer request associated with this TD. */ + td -> ux_ehci_td_transfer_request = transfer_request; + + /* Store the ED associated with this TD. */ + td -> ux_ehci_td_ed = ed; + + /* Mark the TD with the phase. */ + td -> ux_ehci_td_phase |= phase; + + /* Set the PID in the control DWORD of the TD. */ + td -> ux_ehci_td_control = pid; + + /* Set the buffer address if there is a data payload. */ + bp.void_ptr = _ux_utility_physical_address(buffer_address); + td -> ux_ehci_td_bp0 = bp.void_ptr; /* with offset. */ + + /* Fill in the next pages addresses if required. */ + bp.value &= UX_EHCI_PAGE_ALIGN; + td -> ux_ehci_td_bp1 = bp.u8_ptr + UX_EHCI_PAGE_SIZE; + td -> ux_ehci_td_bp2 = bp.u8_ptr + UX_EHCI_PAGE_SIZE * 2; + td -> ux_ehci_td_bp3 = bp.u8_ptr + UX_EHCI_PAGE_SIZE * 3; + td -> ux_ehci_td_bp4 = bp.u8_ptr + UX_EHCI_PAGE_SIZE * 4; + + /* Set the length of the data transfer. We keep its original value. */ + td -> ux_ehci_td_control |= buffer_length << UX_EHCI_TD_LG_LOC; + td -> ux_ehci_td_length = buffer_length; + + /* Add the completion trigger, the default error count, the active bit. */ + td -> ux_ehci_td_control |= UX_EHCI_TD_CERR | UX_EHCI_TD_ACTIVE; + + /* Add the toggle value. This value is only used for control transfers. */ + td -> ux_ehci_td_control |= toggle; + + /* Recall the last TD hooked to the ED. If the value is NULL, this will be the + first TD and should be hooked to the ED itself.. */ + last_td = ed -> ux_ehci_ed_last_td; + + /* Do we hook this TD to the ED? */ + if (last_td == UX_NULL) + { + + /* The TD is hooked to the ED. We set the T bit so that the controller will + not transfer this TD on hook up but when all the TDs have been hooked. + We memorize this TD as the first TD as well. */ + ed -> ux_ehci_ed_first_td = td; + lp.void_ptr = _ux_utility_physical_address(td); + lp.value |= UX_EHCI_TD_T; + ed -> ux_ehci_ed_queue_element = lp.td_ptr; + } + else + { + + /* The TD is hooked to the end of the linked TDs. */ + last_td -> ux_ehci_td_link_pointer = _ux_utility_physical_address(td); + } + + /* Memorize the last TD hooked. */ + ed -> ux_ehci_ed_last_td = td; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_abort.c b/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_abort.c new file mode 100644 index 0000000..92d3619 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_abort.c @@ -0,0 +1,181 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_transfer_abort PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will abort transactions attached to a transfer */ +/* request. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ehci Pointer to EHCI controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_virtual_address Get virtual address */ +/* _ux_utility_mutex_on Get mutex */ +/* _ux_utility_mutex_off Put mutex */ +/* _ux_utility_delay_ms Delay miliseconds */ +/* _ux_hcd_ehci_ed_clean Clean TDs on ED */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ehci_transfer_abort(UX_HCD_EHCI *hcd_ehci,UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_EHCI_HSISO_ED *ied; +UX_EHCI_PERIODIC_LINK_POINTER lp; +UX_TRANSFER **list_head; +UX_TRANSFER *transfer; +ULONG max_load_count; +ULONG remain_count; + + UX_PARAMETER_NOT_USED(hcd_ehci); + + + /* Get the pointer to the endpoint associated with the transfer request*/ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* From the endpoint container, get the address of the physical endpoint. */ + lp.void_ptr = endpoint -> ux_endpoint_ed; + + /* Check if this physical endpoint has been initialized properly! */ + if (lp.void_ptr == UX_NULL) + { + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* Check endpoint type. */ + if ((endpoint -> ux_endpoint_descriptor.bmAttributes & UX_MASK_ENDPOINT_TYPE) == UX_ISOCHRONOUS_ENDPOINT) + { + + /* Lock the periodic table. */ + _ux_utility_mutex_on(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + +#if defined(UX_HCD_EHCI_SPLIT_TRANSFER_ENABLE) + if (endpoint -> ux_endpoint_device -> ux_device_speed != UX_HIGH_SPEED_DEVICE) + { + list_head = &lp.sitd_ptr -> ux_ehci_fsiso_td_transfer_head; + } + else +#endif + { + /* Get ED for the iTD(s). */ + ied = lp.itd_ptr -> ux_ehci_hsiso_td_ed; + + /* Get list head for further process. */ + list_head = &ied -> ux_ehci_hsiso_ed_transfer_head; + + /* Max load count (in 1 ms): 8, 4, 2, 1 ... */ + max_load_count = 8 >> ied -> ux_ehci_hsiso_ed_frinterval_shift; + } + + /* The whole list is aborted. */ + if ((transfer_request == 0) || + (transfer_request == &endpoint -> ux_endpoint_transfer_request) || + (*list_head) == transfer_request) + { + *list_head = UX_NULL; + remain_count = 0; + } + else + { + + /* At least one request remains. */ + remain_count = 1; + + /* Remove it and transfers after it. */ + transfer = (*list_head) -> ux_transfer_request_next_transfer_request; + while(transfer) + { + + /* If next is transfer we expect, remove from it. */ + if (transfer -> ux_transfer_request_next_transfer_request == transfer_request) + { + + /* Point to NULL to remove all things after it. */ + transfer -> ux_transfer_request_next_transfer_request = UX_NULL; + break; + } + + /* Next transfer. */ + transfer = transfer -> ux_transfer_request_next_transfer_request; + + /* Remain plus one. */ + remain_count ++; + } + } + + /* Wait a while so background transfer completed. */ + if (remain_count < max_load_count) + _ux_utility_delay_ms(1); + + /* Release the periodic table. */ + _ux_utility_mutex_off(&hcd_ehci -> ux_hcd_ehci_periodic_mutex); + } + else + + /* Clean the TDs attached to the ED. */ + _ux_hcd_ehci_ed_clean(lp.ed_ptr); + + /* Return successful completion. */ + return(UX_SUCCESS); +} diff --git a/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_request_process.c b/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_request_process.c new file mode 100644 index 0000000..8c1e2df --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ehci_transfer_request_process.c @@ -0,0 +1,92 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** EHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ehci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ehci_transfer_request_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function process the transfer that was completed either */ +/* successfully because of a partial transmission or because of an */ +/* error. The transfer descriptor tells us what to do with it, either */ +/* put a semaphore to the caller or invoke a completion routine. If a */ +/* completion routine is specified, the routine is called and no */ +/* semaphore is put. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* (ux_transfer_request_completion_function) Transfer complete function*/ +/* _ux_utility_semaphore_put Put producer semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* EHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ehci_transfer_request_process(UX_TRANSFER *transfer_request) +{ + + /* Check if there is a function for the transfer completion. */ + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + + /* Yes, so we call it. */ + transfer_request -> ux_transfer_request_completion_function(transfer_request); + else + + /* There is a semaphore so send the signal to the class. */ + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_asynchronous_endpoint_create.c b/common/usbx_host_controllers/src/ux_hcd_ohci_asynchronous_endpoint_create.c new file mode 100644 index 0000000..36127c4 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_asynchronous_endpoint_create.c @@ -0,0 +1,167 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_asynchronous_endpoint_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will create an asynchronous endpoint. The control */ +/* and bulk endpoints fall into this category. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI HCD */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_ed_obtain Obtain a new ED */ +/* _ux_hcd_ohci_register_read Read OHCI register */ +/* _ux_hcd_ohci_register_write Write OHCI register */ +/* _ux_utility_physical_address Get physical address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_asynchronous_endpoint_create(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint) +{ + +UX_DEVICE *device; +UX_OHCI_ED *ed; +UX_OHCI_ED *head_ed; +UX_OHCI_TD *td; +ULONG ohci_register; + + + /* We need to take into account the nature of the HCD to define the max size + of any transfer in the transfer request. */ + endpoint -> ux_endpoint_transfer_request.ux_transfer_request_maximum_length = UX_OHCI_MAX_PAYLOAD; + + /* Obtain a ED for this new endpoint. This ED will live as long as the endpoint is active and + will be the container for the TDs. */ + ed = _ux_hcd_ohci_ed_obtain(hcd_ohci); + if (ed == UX_NULL) + return(UX_NO_ED_AVAILABLE); + + /* Obtain a dummy TD for terminating the ED transfer chain. */ + td = _ux_hcd_ohci_regular_td_obtain(hcd_ohci); + if (td == UX_NULL) + { + + ed -> ux_ohci_ed_status = UX_UNUSED; + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the ED to the endpoint container. */ + endpoint -> ux_endpoint_ed = (VOID *) ed; + + /* Now do the opposite, attach the ED container to the physical ED. */ + ed -> ux_ohci_ed_endpoint = endpoint; + + /* Program the ED for subsequent transfers. We need to set the following things: + 1) Address of the device + 2) endpoint number + 3) speed + 4) format of TD + 5) maximum packet size */ + device = endpoint -> ux_endpoint_device; + ed -> ux_ohci_ed_dw0 = device -> ux_device_address | + ((ULONG) (endpoint -> ux_endpoint_descriptor.bEndpointAddress & ~UX_ENDPOINT_DIRECTION)) << 7 | + ((ULONG) endpoint -> ux_endpoint_descriptor.wMaxPacketSize) << 16; + + if (device -> ux_device_speed == UX_LOW_SPEED_DEVICE) + ed -> ux_ohci_ed_dw0 |= UX_OHCI_ED_LOW_SPEED; + + /* Hook the TD to both the tail and head of the ED. */ + ed -> ux_ohci_ed_tail_td = _ux_utility_physical_address(td); + ed -> ux_ohci_ed_head_td = _ux_utility_physical_address(td); + + /* We now need to get the type of transfer (control or bulk) to hook this ED to the appropriate list. + We also enable the appropriate list. */ + switch ((endpoint -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + + head_ed = (UX_OHCI_ED *) _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_CONTROL_HEAD_ED); + ed -> ux_ohci_ed_next_ed = head_ed; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL_HEAD_ED, (ULONG) ed); + ohci_register = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_CONTROL); + ohci_register |= OHCI_HC_CR_CLE; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL, ohci_register); + break; + + + case UX_BULK_ENDPOINT: + + head_ed = (UX_OHCI_ED *) _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_BULK_HEAD_ED); + ed -> ux_ohci_ed_next_ed = head_ed; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_BULK_HEAD_ED, (ULONG) ed); + ohci_register = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_CONTROL); + ohci_register |= OHCI_HC_CR_BLE; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL, ohci_register); + break; + + default: + + head_ed = UX_NULL; + } + + /* Build the back chaining pointer. The previous head ED needs to know about the + inserted ED. */ + if (head_ed != UX_NULL) + head_ed -> ux_ohci_ed_previous_ed = ed; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_asynchronous_endpoint_destroy.c b/common/usbx_host_controllers/src/ux_hcd_ohci_asynchronous_endpoint_destroy.c new file mode 100644 index 0000000..fb2cee4 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_asynchronous_endpoint_destroy.c @@ -0,0 +1,201 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" +#include "ux_hcd_ohci.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_asynchronous_endpoint_destroy PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will destroy an asynchronous endpoint. The control */ +/* and bulk endpoints fall into this category. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI HCD */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_register_read Read OHCI register */ +/* _ux_hcd_ohci_register_write Write OHCI register */ +/* _ux_utility_virtual_address Get virtual address */ +/* _ux_utility_delay_ms Delay ms */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_asynchronous_endpoint_destroy(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint) +{ + +UX_OHCI_ED *ed; +UX_OHCI_ED *previous_ed; +UX_OHCI_ED *next_ed; +UX_OHCI_TD *tail_td; +UX_OHCI_TD *head_td; +ULONG value_td; +ULONG ohci_register; + + + /* From the endpoint container fetch the OHCI ED descriptor. */ + ed = (UX_OHCI_ED*) endpoint -> ux_endpoint_ed; + + /* Check if this physical endpoint has been initialized properly! */ + if (ed == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* The endpoint may be active. If so, set the skip bit. */ + ed -> ux_ohci_ed_dw0 |= UX_OHCI_ED_SKIP; + + /* Wait for the controller to finish the current frame processing. */ + _ux_utility_delay_ms(1); + + /* Get the previous ED in the list for this ED. */ + previous_ed = ed -> ux_ohci_ed_previous_ed; + + /* Get the next ED in the list for this ED. */ + next_ed = ed -> ux_ohci_ed_next_ed; + + /* If the previous ED is NULL, we are at trying to remove the head ED. */ + if (previous_ed == UX_NULL) + { + + switch ((endpoint -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + + /* Check if the next control endpoint is NULL. */ + if (next_ed == UX_NULL) + { + + ohci_register = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_CONTROL); + ohci_register &= ~OHCI_HC_CR_CLE; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL, ohci_register); + } + + /* Store the new endpoint in the Control list. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL_HEAD_ED, (ULONG) next_ed); + break; + + + case UX_BULK_ENDPOINT: + + /* Check if the next bulk endpoint is NULL. */ + if (next_ed == UX_NULL) + { + + ohci_register = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_CONTROL); + ohci_register &= ~OHCI_HC_CR_BLE; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL, ohci_register); + } + + /* Store the new endpoint in the Bulk list */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_BULK_HEAD_ED, (ULONG) next_ed); + break; + } + } + else + { + + /* The previous ED points now to the ED after the ED we are removing. */ + previous_ed -> ux_ohci_ed_next_ed = next_ed; + } + + /* Update the previous ED pointer in the next ED if exists. */ + if (next_ed != UX_NULL) + next_ed -> ux_ohci_ed_previous_ed = previous_ed; + + /* We use the tail TD as a pointer to the Dummy TD. */ + tail_td = (UX_OHCI_TD *) _ux_utility_virtual_address(ed -> ux_ohci_ed_tail_td); + + /* Ensure that the potential Halt bit is removed in the head ED. */ + value_td = (ULONG) _ux_utility_virtual_address(ed -> ux_ohci_ed_head_td) & UX_OHCI_ED_MASK_TD; + head_td = (UX_OHCI_TD *) _ux_utility_physical_address((VOID *) value_td); + ed -> ux_ohci_ed_head_td = head_td; + + /* Remove all the tds from this ED and leave the head and tail pointing + to the dummy TD. */ + tail_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_tail_td); + + /* Free all tds attached to the ED */ + while (head_td != tail_td) + { + + /* Update the head TD with the next TD. */ + ed -> ux_ohci_ed_head_td = head_td -> ux_ohci_td_next_td; + + /* Mark the current head TD as free. */ + head_td -> ux_ohci_td_status = UX_UNUSED; + + /* Now the new head TD is the next TD in the chain. */ + head_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_head_td); + } + + /* We need to free the dummy TD that was attached to the ED. */ + tail_td -> ux_ohci_td_status = UX_UNUSED; + + + /* Now we can safely make the ED free. */ + ed -> ux_ohci_ed_status = UX_UNUSED; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_controller_disable.c b/common/usbx_host_controllers/src/ux_hcd_ohci_controller_disable.c new file mode 100644 index 0000000..0edbc33 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_controller_disable.c @@ -0,0 +1,93 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_controller_disable PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will disable the OHCI controller. The controller */ +/* will release all its resources (memory, IO ...). After this, the */ +/* controller will not send SOF any longer. All transactions should */ +/* have been completed, all classes should have been closed. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI HCD */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_register_write Write OHCI register */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_controller_disable(UX_HCD_OHCI *hcd_ohci) +{ + +UX_HCD *hcd; +ULONG ohci_register; + + + /* Point to the generic portion of the host controller structure instance. */ + hcd = hcd_ohci -> ux_hcd_ohci_hcd_owner; + + /* Set the controller to disabled state. */ + ohci_register = OHCI_HC_CR_RESET; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL, ohci_register); + + /* Reflect the state of the controller in the main structure. */ + hcd -> ux_hcd_status = UX_HCD_STATUS_HALTED; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_done_queue_process.c b/common/usbx_host_controllers/src/ux_hcd_ohci_done_queue_process.c new file mode 100644 index 0000000..a104172 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_done_queue_process.c @@ -0,0 +1,340 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_done_queue_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function process the done queue that was posted by the */ +/* controller during the last interrupt. The bad news is that the */ +/* list of the TDs in the queue is in the opposite order of their */ +/* actual completion. This FIFO made the OHCI design easier but the */ +/* software has to work harder! */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI HCD */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* (ux_transfer_request_completion_function) */ +/* Transfer completion function */ +/* _ux_hcd_ohci_endpoint_error_clear Clear endpoint error */ +/* _ux_hcd_ohci_endpoint_reset Reset endpoint */ +/* _ux_hcd_ohci_frame_number_get Get frame number */ +/* _ux_hcd_ohci_next_td_clean Clean next TD */ +/* _ux_hcd_ohci_register_read Read OHCI register */ +/* _ux_hcd_ohci_register_write Write OHCI register */ +/* _ux_utility_semaphore_put Put producer semaphore */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ohci_done_queue_process(UX_HCD_OHCI *hcd_ohci) +{ + +UX_ENDPOINT *endpoint; +UX_OHCI_TD *td; +UX_OHCI_ISO_TD *iso_td; +UX_OHCI_TD *previous_td; +UX_OHCI_TD *next_td; +UINT td_error_code; +UX_TRANSFER *transfer_request; +ULONG ohci_register_interrupt; +ULONG transaction_length; +ULONG current_frame; + + + /* Get the first entry of the done queue. It may be NULL which means there is nothing to do! + The LSB of the TD pointer may be set by the OHCI controller to indicate that the Interrupt + status of the controller should be read. The TDs in the list are using physical addresses. + They need to be translated into virtual addresses. */ + next_td = _ux_utility_virtual_address((VOID *) ((ULONG) hcd_ohci -> ux_hcd_ohci_done_head & 0xfffffff0)); + + /* Reset the last TD in the chain. */ + previous_td = UX_NULL; + td = UX_NULL; + + /* The TD we have now is the last in the FIFO, re-traverse the chain to get the TDs in the + chronological order. */ + while (next_td != UX_NULL) + { + + td = next_td; + next_td = _ux_utility_virtual_address(td -> ux_ohci_td_next_td); + td -> ux_ohci_td_next_td = previous_td; + previous_td = td; + } + + /* Process each TD in their chronological order now. The TD pointer now has the first TD in the + list, all values are in virtual addresses. */ + while (td != UX_NULL) + { + + /* Get the pointer to the transfer request attached with this TD. */ + transfer_request = td -> ux_ohci_td_transfer_request; + + /* Get the endpoint associated with the transfer request */ + endpoint = transfer_request -> ux_transfer_request_endpoint; + + /* Retrieve the error code for this transaction. There are 3 types of errors: + transmission, sequence, system. */ + td_error_code = td -> ux_ohci_td_dw0 >> UX_OHCI_TD_CC; + + /* The handling of the isoch TD is slightly different. */ + switch ((endpoint -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + case UX_BULK_ENDPOINT: + case UX_INTERRUPT_ENDPOINT: + + switch (td_error_code) + { + + case UX_OHCI_NO_ERROR: + + /* No error on the transmission of this TD. Update the length of the transfer request. */ + transfer_request -> ux_transfer_request_actual_length += td -> ux_ohci_td_length; + + /* Check at the phase of the transfer, if this is a SETUP or DATA phases for a control + endpoint, we wait for the setup phase or any phase for other types of endpoints. */ + if ((td -> ux_ohci_td_status & UX_OHCI_TD_SETUP_PHASE) || (td -> ux_ohci_td_status & UX_OHCI_TD_DATA_PHASE)) + break; + + /* Either this is a non control endpoint or it is the status phase and we are done. */ + if (transfer_request -> ux_transfer_request_actual_length == transfer_request -> ux_transfer_request_requested_length) + { + + transfer_request -> ux_transfer_request_completion_code = UX_SUCCESS; + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + } + break; + + + case UX_OHCI_ERROR_DATA_UNDERRUN: + + /* No error on the transmission of this TD but all data is not accounted for. This is typically + a short packet and OHCI report it as an error. This allows for the ED to be halted and further + attached TDs to be stopped. In this case, compute the correct received\sent length and + process the transfer request. */ + transfer_request -> ux_transfer_request_actual_length += td -> ux_ohci_td_length - ((ULONG) td -> ux_ohci_td_be - + (ULONG) td -> ux_ohci_td_cbp) - 1; + + /* Check at the phase of the transfer, if this is a SETUP or DATA phases for a control endpoint, + we wait for the setup phase or any phase for other types of endpoints. */ + if ((td -> ux_ohci_td_status & UX_OHCI_TD_SETUP_PHASE) || (td -> ux_ohci_td_status & UX_OHCI_TD_DATA_PHASE)) + break; + + /* We need to reset the error bit in the ED. */ + _ux_hcd_ohci_endpoint_error_clear(hcd_ohci, endpoint); + + /* Either this is a non control endpoint or it is the status phase and we are done */ + transfer_request -> ux_transfer_request_completion_code = UX_SUCCESS; + _ux_hcd_ohci_next_td_clean(td); + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + + break; + + + case UX_OHCI_ERROR_STALL: + + /* A stall condition happens when the device refuses the requested command or when a + parameter in the command is wrong. We retire the transfer_request and mark the error. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_STALLED; + _ux_hcd_ohci_next_td_clean(td); + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_STALLED, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We need to reset the error bit in the ED. */ + _ux_hcd_ohci_endpoint_reset(hcd_ohci, endpoint); + break; + + + case UX_OHCI_ERROR_DEVICE_NOT_RESPONDING: + + /* A stall condition happens when the device does not respond to the request. This mostly + happens at the first GET_DESCRIPTOR after the port is enabled. This error has to be + picked up by the enumeration module to reset the port and retry the command. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_NO_ANSWER; + _ux_hcd_ohci_next_td_clean(td); + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_NO_ANSWER, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We need to reset the error bit in the ED */ + _ux_hcd_ohci_endpoint_reset(hcd_ohci, endpoint); + break; + + + default: + + /* Any other errors default to this section. The command has been repeated 3 times + and there is still a problem. The endpoint probably should be reset. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_ERROR; + _ux_hcd_ohci_next_td_clean(td); + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_ERROR, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* We need to reset the error bit in the ED. */ + _ux_hcd_ohci_endpoint_reset(hcd_ohci, endpoint); + break; + } + break; + + + case UX_ISOCHRONOUS_ENDPOINT: + + /* The length of the transfer is in the PSW. */ + iso_td = (UX_OHCI_ISO_TD *) td; + + switch (td_error_code) + { + + case UX_OHCI_NO_ERROR: + + /* No error on the transmission of this TD. All data is accounted for. Check for the + last TD in the transfer request. If last, process the transfer request. The method + to calculate the length of the transaction is different between a IN and OUT + transactions. For a OUT, if the PSW is 0, then all data was transmitted. For an IN + the PSW indicates the number of bytes received. */ + transaction_length = iso_td -> ux_ohci_iso_td_offset_psw[0] & UX_OHCI_ISO_TD_OFFSET; + + if ((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + { + + transfer_request -> ux_transfer_request_actual_length += transaction_length; + } + else + { + + if (transaction_length == 0) + transfer_request -> ux_transfer_request_actual_length += iso_td -> ux_ohci_iso_td_length; + else + transfer_request -> ux_transfer_request_actual_length += transaction_length; + } + + /* Check if the transfer request is complete or if this is an IN transaction and the length received + is less than the max packet size. */ + if ((transfer_request -> ux_transfer_request_actual_length == transfer_request -> ux_transfer_request_requested_length) || + (((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) && + (transaction_length < transfer_request -> ux_transfer_request_packet_length))) + { + + transfer_request -> ux_transfer_request_completion_code = UX_SUCCESS; + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + } + break; + + + case UX_OHCI_ERROR_DATA_OVERRRUN: + + /* In this case, we have missed the frame for the isoch transfer. */ + _ux_hcd_ohci_frame_number_get(hcd_ohci, ¤t_frame); + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_MISSED_FRAME; + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_MISSED_FRAME, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + break; + + + default: + + /* Some other error happened, in isoch transfer, there is not much we can do. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_ERROR; + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + transfer_request -> ux_transfer_request_completion_function(transfer_request); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_ERROR, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + break; + } + } + + /* Free the TD that was just treated. */ + td -> ux_ohci_td_status = UX_UNUSED; + + /* And continue the TD loop. */ + td = td -> ux_ohci_td_next_td; + } + + /* The OHCI controller is now ready to receive the next done queue. We need to + reawake the OHCI controller on the WDH signal. */ + ohci_register_interrupt = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_INTERRUPT_ENABLE); + ohci_register_interrupt |= OHCI_HC_INT_WDH; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_INTERRUPT_ENABLE, ohci_register_interrupt); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_ed_obtain.c b/common/usbx_host_controllers/src/ux_hcd_ohci_ed_obtain.c new file mode 100644 index 0000000..1f8c660 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_ed_obtain.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_ed_obtain PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains a free ED from the ED list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI HCD */ +/* */ +/* OUTPUT */ +/* */ +/* UX_OHCI_ED * Pointer to ED */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_set Set memory block */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_OHCI_ED *_ux_hcd_ohci_ed_obtain(UX_HCD_OHCI *hcd_ohci) +{ + +UX_OHCI_ED *ed; +ULONG ed_index; + + + /* Start the search from the beginning of the list. */ + ed = hcd_ohci -> ux_hcd_ohci_ed_list; + for (ed_index = 0; ed_index < _ux_system_host -> ux_system_host_max_ed; ed_index++) + { + + /* Check the ED status, a free ED is marked with the UNUSED flag. */ + if (ed -> ux_ohci_ed_status == UX_UNUSED) + { + + /* The ED may have been used, so we reset all fields. */ + _ux_utility_memory_set(ed, 0, sizeof(UX_OHCI_ED)); + + /* This ED is now marked as USED. */ + ed -> ux_ohci_ed_status = UX_USED; + + /* Success, return the ED pointer. */ + return(ed); + } + + /* Point to the next ED. */ + ed++; + } + + /* There is no available ED in the ED list, return a NULL. */ + return(UX_NULL); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_endpoint_error_clear.c b/common/usbx_host_controllers/src/ux_hcd_ohci_endpoint_error_clear.c new file mode 100644 index 0000000..81ab6cd --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_endpoint_error_clear.c @@ -0,0 +1,90 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_endpoint_error_clear PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will clear the error bit in a OHCI endpoint. This */ +/* command, unlike the reset command does not clear the toggle bit. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI HCD */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_endpoint_error_clear(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint) +{ + +UX_OHCI_ED *ed; +ULONG td_value; + + + /* From the endpoint container fetch the OHCI ED descriptor. */ + ed = (UX_OHCI_ED *) endpoint -> ux_endpoint_ed; + + /* Reset the Error bit in the Head TD. */ + td_value = (ULONG) ed -> ux_ohci_ed_head_td; + td_value &= ~UX_OHCI_ED_HALTED; + ed -> ux_ohci_ed_head_td = (UX_OHCI_TD *) td_value; + + /* This operation never fails! */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_endpoint_reset.c b/common/usbx_host_controllers/src/ux_hcd_ohci_endpoint_reset.c new file mode 100644 index 0000000..110242e --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_endpoint_reset.c @@ -0,0 +1,89 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_endpoint_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will reset an endpoint. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI HCD */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_endpoint_reset(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint) +{ + +UX_OHCI_ED *ed; +ULONG td_value; + + + /* From the endpoint container fetch the OHCI ED descriptor. */ + ed = (UX_OHCI_ED *) endpoint -> ux_endpoint_ed; + + /* Reset the data0/data1 toggle bit in the Head TD. */ + td_value = (ULONG) ed -> ux_ohci_ed_head_td; + td_value &= UX_OHCI_ED_MASK_TD; + ed -> ux_ohci_ed_head_td = (UX_OHCI_TD *) td_value; + + /* This operation never fails! */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_entry.c b/common/usbx_host_controllers/src/ux_hcd_ohci_entry.c new file mode 100644 index 0000000..31ef6c0 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_entry.c @@ -0,0 +1,274 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function dispatches the HCD function internally to the OHCI */ +/* controller driver routines. */ +/* */ +/* INPUT */ +/* */ +/* HCD Pointer to HCD */ +/* function Function for driver to perform*/ +/* parameter Pointer to parameter(s) */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_asynchronous_endpoint_create Create async endpoint */ +/* _ux_hcd_ohci_asynchronous_endpoint_destroy Destroy async endpoint */ +/* _ux_hcd_ohci_controller_disable Disable controller */ +/* _ux_hcd_ohci_done_queue_process Process done queue */ +/* _ux_hcd_ohci_endpoint_reset Reset endpoint */ +/* _ux_hcd_ohci_frame_number_get Get frame number */ +/* _ux_hcd_ohci_frame_number_set Set frame number */ +/* _ux_hcd_ohci_interrupt_endpoint_create Create interrupt endpoint*/ +/* _ux_hcd_ohci_isochronous_endpoint_create Create isoch endpoint */ +/* _ux_hcd_ohci_periodic_endpoint_destroy Destroy periodic endpoint*/ +/* _ux_hcd_ohci_port_enable Enable port */ +/* _ux_hcd_ohci_port_disable Disable port */ +/* _ux_hcd_ohci_port_reset Reset port */ +/* _ux_hcd_ohci_port_resume Resume port */ +/* _ux_hcd_ohci_port_status_get Get port status */ +/* _ux_hcd_ohci_port_suspend Suspend port */ +/* _ux_hcd_ohci_power_down_port Power down port */ +/* _ux_hcd_ohci_power_on_port Power on port */ +/* _ux_hcd_ohci_request_transfer Request transfer */ +/* _ux_hcd_ohci_transfer_abort Abort transfer */ +/* */ +/* CALLED BY */ +/* */ +/* Host Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_entry(UX_HCD *hcd, UINT function, VOID *parameter) +{ + +UINT status; +UX_HCD_OHCI *hcd_ohci; + + + /* Check the status of the controller. */ + if (hcd -> ux_hcd_status == UX_UNUSED) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_CONTROLLER_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONTROLLER_UNKNOWN, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONTROLLER_UNKNOWN); + } + + /* Get the pointer to the OHCI HCD. */ + hcd_ohci = (UX_HCD_OHCI *) hcd -> ux_hcd_controller_hardware; + + /* look at the function and route it. */ + switch(function) + { + + case UX_HCD_DISABLE_CONTROLLER: + + status = _ux_hcd_ohci_controller_disable(hcd_ohci); + break; + + + case UX_HCD_GET_PORT_STATUS: + + status = _ux_hcd_ohci_port_status_get(hcd_ohci, (ULONG) parameter); + break; + + + case UX_HCD_ENABLE_PORT: + + status = _ux_hcd_ohci_port_enable(hcd_ohci, (ULONG) parameter); + break; + + + case UX_HCD_DISABLE_PORT: + + status = _ux_hcd_ohci_port_disable(hcd_ohci, (ULONG) parameter); + break; + + + case UX_HCD_POWER_ON_PORT: + + status = _ux_hcd_ohci_power_on_port(hcd_ohci, (ULONG) parameter); + break; + + + case UX_HCD_POWER_DOWN_PORT: + + status = _ux_hcd_ohci_power_down_port(hcd_ohci, (ULONG) parameter); + break; + + + case UX_HCD_SUSPEND_PORT: + + status = _ux_hcd_ohci_port_suspend(hcd_ohci, (ULONG) parameter); + break; + + + case UX_HCD_RESUME_PORT: + + status = _ux_hcd_ohci_port_resume(hcd_ohci, (UINT) parameter); + break; + + + case UX_HCD_RESET_PORT: + + status = _ux_hcd_ohci_port_reset(hcd_ohci, (ULONG) parameter); + break; + + + case UX_HCD_GET_FRAME_NUMBER: + + status = _ux_hcd_ohci_frame_number_get(hcd_ohci, (ULONG *) parameter); + break; + + + case UX_HCD_SET_FRAME_NUMBER: + + _ux_hcd_ohci_frame_number_set(hcd_ohci, (ULONG) parameter); + status = UX_SUCCESS; + break; + + + case UX_HCD_TRANSFER_REQUEST: + + status = _ux_hcd_ohci_request_transfer(hcd_ohci, (UX_TRANSFER *) parameter); + break; + + + case UX_HCD_TRANSFER_ABORT: + + status = _ux_hcd_ohci_transfer_abort(hcd_ohci, (UX_TRANSFER *) parameter); + break; + + + case UX_HCD_CREATE_ENDPOINT: + + switch ((((UX_ENDPOINT*) parameter) -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + case UX_BULK_ENDPOINT: + + status = _ux_hcd_ohci_asynchronous_endpoint_create(hcd_ohci, (UX_ENDPOINT*) parameter); + break; + + + case UX_INTERRUPT_ENDPOINT: + + status = _ux_hcd_ohci_interrupt_endpoint_create(hcd_ohci, (UX_ENDPOINT*) parameter); + break; + + + case UX_ISOCHRONOUS_ENDPOINT: + + status = _ux_hcd_ohci_isochronous_endpoint_create(hcd_ohci, (UX_ENDPOINT*) parameter); + break; + + } + break; + + + case UX_HCD_DESTROY_ENDPOINT: + + switch ((((UX_ENDPOINT*) parameter) -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + case UX_BULK_ENDPOINT: + + status = _ux_hcd_ohci_asynchronous_endpoint_destroy(hcd_ohci, (UX_ENDPOINT*) parameter); + break; + + case UX_INTERRUPT_ENDPOINT: + case UX_ISOCHRONOUS_ENDPOINT: + + status = _ux_hcd_ohci_periodic_endpoint_destroy(hcd_ohci, (UX_ENDPOINT*) parameter); + break; + + } + break; + + + case UX_HCD_RESET_ENDPOINT: + + status = _ux_hcd_ohci_endpoint_reset(hcd_ohci, (UX_ENDPOINT*) parameter); + break; + + + case UX_HCD_PROCESS_DONE_QUEUE: + + _ux_hcd_ohci_done_queue_process(hcd_ohci); + status = UX_SUCCESS; + break; + + + default: + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_FUNCTION_NOT_SUPPORTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_FUNCTION_NOT_SUPPORTED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* Set status to not supported. */ + status = UX_FUNCTION_NOT_SUPPORTED; + } + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_frame_number_get.c b/common/usbx_host_controllers/src/ux_hcd_ohci_frame_number_get.c new file mode 100644 index 0000000..8eb44ca --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_frame_number_get.c @@ -0,0 +1,83 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_frame_number_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will return the frame number currently used by the */ +/* controller. This function is mostly used for isochronous purposes. */ +/* It is easier to read the frame number off the HCCA structure */ +/* because this can be done without going back to the controller. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* frame_number Pointer to frame number */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_frame_number_get(UX_HCD_OHCI *hcd_ohci, ULONG *frame_number) +{ + + /* Pickup the frame number. */ + *frame_number = (ULONG) hcd_ohci -> ux_hcd_ohci_hcca -> ux_hcd_ohci_hcca_frame_number; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_frame_number_set.c b/common/usbx_host_controllers/src/ux_hcd_ohci_frame_number_set.c new file mode 100644 index 0000000..96d90c2 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_frame_number_set.c @@ -0,0 +1,81 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_frame_number_set PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will set the current frame number to the one */ +/* specified. This function is mostly used for isochronous purposes. */ +/* Here we need to write to the host controller which in turn will */ +/* update the HCCA at the end of the frame. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* frame_number Frame number to set */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_register_write Write OHCI register */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ohci_frame_number_set(UX_HCD_OHCI *hcd_ohci, ULONG frame_number) +{ + + /* Write to OHCI register. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_FM_NUMBER, frame_number & 0xffff); + return; +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_initialize.c b/common/usbx_host_controllers/src/ux_hcd_ohci_initialize.c new file mode 100644 index 0000000..509e424 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_initialize.c @@ -0,0 +1,224 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_initialize PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the OHCI controller. It sets the dma */ +/* areas, programs all the OHCI registers, setup the ED and TD */ +/* containers, sets the control, and builds the periodic lists. */ +/* */ +/* INPUT */ +/* */ +/* HCD Pointer to HCD */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_periodic_tree_create Create OHCI periodic tree */ +/* _ux_hcd_ohci_power_root_hubs Power root HUBs */ +/* _ux_hcd_ohci_register_read Read OHCI register */ +/* _ux_hcd_ohci_register_write Write OHCI register */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_mutex_on Get mutex protection */ +/* _ux_utility_mutex_off Release mutex protection */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_set_interrupt_handler Setup interrupt handler */ +/* */ +/* CALLED BY */ +/* */ +/* Host Stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_initialize(UX_HCD *hcd) +{ + +UX_HCD_OHCI *hcd_ohci; +ULONG ohci_register; +UINT index_loop; +UINT status; + + + /* The controller initialized here is of OHCI type. */ + hcd -> ux_hcd_controller_type = UX_OHCI_CONTROLLER; + + /* Initialize the max bandwidth for periodic endpoints. On OHCI, the spec says no + more than 90% to be allocated for periodic. */ + hcd -> ux_hcd_available_bandwidth = UX_OHCI_AVAILABLE_BANDWIDTH; + + /* Allocate memory for this OHCI HCD instance. */ + hcd_ohci = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_REGULAR_MEMORY, sizeof(UX_HCD_OHCI)); + if (hcd_ohci == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Set the pointer to the OHCI HCD. */ + hcd -> ux_hcd_controller_hardware = (VOID *) hcd_ohci; + + /* Save the HCOR address. */ + hcd_ohci -> ux_hcd_ohci_hcor = (ULONG *) hcd -> ux_hcd_io; + + /* Set the generic HCD owner for the OHCI HCD. */ + hcd_ohci -> ux_hcd_ohci_hcd_owner = hcd; + + /* Initialize the function collector for this HCD. */ + hcd -> ux_hcd_entry_function = _ux_hcd_ohci_entry; + + /* Set the state of the controller to HALTED first. */ + hcd -> ux_hcd_status = UX_HCD_STATUS_HALTED; + + /* get an DMA safe address for the HCCA. This block of memory is to be aligned + on 256 bytes. */ + hcd_ohci -> ux_hcd_ohci_hcca = _ux_utility_memory_allocate(UX_ALIGN_256, UX_CACHE_SAFE_MEMORY, sizeof(UX_HCD_OHCI_HCCA)); + if (hcd_ohci -> ux_hcd_ohci_hcca == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Allocate the list of eds. All eds are allocated on 16 byte memory boundary. */ + hcd_ohci -> ux_hcd_ohci_ed_list = _ux_utility_memory_allocate(UX_ALIGN_16, UX_CACHE_SAFE_MEMORY, sizeof(UX_OHCI_ED) * _ux_system_host -> ux_system_host_max_ed); + if (hcd_ohci -> ux_hcd_ohci_ed_list == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Allocate the list of tds. All tds are allocated on 32 byte memory boundary. */ + hcd_ohci -> ux_hcd_ohci_td_list = _ux_utility_memory_allocate(UX_ALIGN_32, UX_CACHE_SAFE_MEMORY, sizeof(UX_OHCI_TD) * _ux_system_host -> ux_system_host_max_td); + if (hcd_ohci -> ux_hcd_ohci_td_list == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Allocate the list of isochronous tds. All tds are allocated on 32 byte memory boundary. */ + hcd_ohci -> ux_hcd_ohci_iso_td_list = _ux_utility_memory_allocate(UX_ALIGN_32, UX_CACHE_SAFE_MEMORY, sizeof(UX_OHCI_ISO_TD) * _ux_system_host -> ux_system_host_max_iso_td); + if (hcd_ohci -> ux_hcd_ohci_td_list == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + /* Initialize the periodic tree. */ + status = _ux_hcd_ohci_periodic_tree_create(hcd_ohci); + if (status != UX_SUCCESS) + return(status); + + /* Read the OHCI controller version, it is either USB 1.0 or 1.1. This is important for + filtering INT out endpoints on a 1.0 OHCI. */ + hcd -> ux_hcd_version = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_REVISION); + + /* Set the state of the OHCI controller to reset in the control register. + This is not compulsory but some controllers demand to start in this state. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL, 0); + + /* The following is time critical. If we get interrupted here, the controller will go in + suspend mode. Get the protection mutex. */ + _ux_utility_mutex_on(&_ux_system -> ux_system_mutex); + + /* Send the reset command to the controller. The controller should ack + this command within 10us. We try this several time and check for timeout. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_COMMAND_STATUS, OHCI_HC_CS_HCR); + + for (index_loop = 0; index_loop < UX_OHCI_RESET_RETRY; index_loop++) + { + + ohci_register = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_COMMAND_STATUS); + if ((ohci_register & OHCI_HC_CS_HCR) == 0) + break; + } + + /* Check if the controller is reset properly. */ + if ((ohci_register & OHCI_HC_CS_HCR) != 0) + { + + /* Release the thread protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_CONTROLLER_INIT_FAILED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_CONTROLLER_INIT_FAILED, 0, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_CONTROLLER_INIT_FAILED); + } + + /* Set the HCCA pointer to the HCOR. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_HCCA, (ULONG) _ux_utility_physical_address(hcd_ohci -> ux_hcd_ohci_hcca)); + + /* For now and until we have control and bulk ED, reset the control and bulk head registers. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL_HEAD_ED, 0); + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL_CURRENT_ED, 0); + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_BULK_HEAD_ED, 0); + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_BULK_CURRENT_ED, 0); + + /* Turn on the OHCI controller functional registers we will use after this operation, + the controller is operational. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_CONTROL, OHCI_HC_CONTROL_VALUE); + hcd -> ux_hcd_status = UX_HCD_STATUS_OPERATIONAL; + + /* We can safely release the mutex protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* Set the controller interval. */ + ohci_register = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_FM_INTERVAL) & OHCI_HC_FM_INTERVAL_CLEAR; + ohci_register |= OHCI_HC_FM_INTERVAL_SET; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_FM_INTERVAL, ohci_register); + + /* Set the default Periodic Start value. In some controller, a reset will set the default value + but in some controller this value has to be set manually (like the LPC2468. ) */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_PERIODIC_START, UX_OHCI_HC_PERIODIC_START_DEFAULT); + + /* Reset all the OHCI interrupts and re-enable only the ones we will use. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_INTERRUPT_DISABLE, OHCI_HC_INTERRUPT_DISABLE_ALL); + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_INTERRUPT_ENABLE, OHCI_HC_INTERRUPT_ENABLE_NORMAL); + + /* Get the number of ports on the controller. The number of ports needs to be reflected both + for the generic HCD container and the local OHCI container. */ + ohci_register = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_RH_DESCRIPTOR_A); + hcd -> ux_hcd_nb_root_hubs = (UINT) (ohci_register & 0xff); + hcd_ohci -> ux_hcd_ohci_nb_root_hubs = (UINT) (ohci_register & 0xff); + + /* All ports must now be powered to pick up device insertion. */ + _ux_hcd_ohci_power_root_hubs(hcd_ohci); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_interrupt_endpoint_create.c b/common/usbx_host_controllers/src/ux_hcd_ohci_interrupt_endpoint_create.c new file mode 100644 index 0000000..5ecf246 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_interrupt_endpoint_create.c @@ -0,0 +1,210 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_interrupt_endpoint_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will create an interrupt endpoint. The interrupt */ +/* endpoint has an interval of operation from 1 to 255. In OHCI, the */ +/* hardware assisted interrupt is from 1 to 32. */ +/* */ +/* This routine will match the best interval for the OHCI hardware. */ +/* It will also determine the best node to hook the endpoint based on */ +/* the load that already exists on the horizontal ED chain. */ +/* */ +/* For the ones curious about this coding. The tricky part is to */ +/* understand how the interrupt matrix is constructed. We have used */ +/* eds with the skip bit on to build a frame of anchor eds. Each ED */ +/* creates a node for an appropriate combination of interval */ +/* frequency in the list. */ +/* */ +/* After obtaining a pointer to the list with the lowest traffic, we */ +/* traverse the list from the highest interval until we reach the */ +/* interval required. At that node, we anchor our real ED to the node */ +/* and link the ED that was attached to the node to our ED. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_ed_obtain Obtain OHCI ED */ +/* _ux_hcd_ohci_least_traffic_list_get Get least traffic list */ +/* _ux_hcd_ohci_regular_td_obtain Obtain OHCI regular TD */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_interrupt_endpoint_create(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint) +{ + +UX_DEVICE *device; +UX_OHCI_ED *ed; +UX_OHCI_ED *ed_list; +UX_OHCI_ED *next_ed; +UX_OHCI_TD *td; +UINT interval; +UINT interval_index; +UINT interval_ohci; + + + /* Obtain a ED for this new endpoint. This ED will live as long as the endpoint + is active and will be the container for the tds. */ + ed = _ux_hcd_ohci_ed_obtain(hcd_ohci); + if (ed == UX_NULL) + return(UX_NO_ED_AVAILABLE); + + /* Obtain a dummy TD for terminating the ED transfer chain. */ + td = _ux_hcd_ohci_regular_td_obtain(hcd_ohci); + if (td == UX_NULL) + { + + ed -> ux_ohci_ed_status = UX_UNUSED; + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the ED to the endpoint container. */ + endpoint -> ux_endpoint_ed = (VOID *) ed; + + /* Program the ED for subsequent transfers we need to set the following things: + + 1) Address of the device + 2) endpoint number + 3) speed + 4) format of TD + 5) maximum packet size */ + device = endpoint -> ux_endpoint_device; + ed -> ux_ohci_ed_dw0 = device -> ux_device_address | + ((ULONG) (endpoint -> ux_endpoint_descriptor.bEndpointAddress & ~UX_ENDPOINT_DIRECTION)) << 7 | + ((ULONG) endpoint -> ux_endpoint_descriptor.wMaxPacketSize) << 16; + + if (device -> ux_device_speed == UX_LOW_SPEED_DEVICE) + ed -> ux_ohci_ed_dw0 |= UX_OHCI_ED_LOW_SPEED; + + /* Hook the TD to both the tail and head of the ED. */ + ed -> ux_ohci_ed_tail_td = _ux_utility_physical_address(td); + ed -> ux_ohci_ed_head_td = _ux_utility_physical_address(td); + + /* Get the list index with the least traffic. */ + ed_list = _ux_hcd_ohci_least_traffic_list_get(hcd_ohci); + + /* Get the interval for the endpoint and match it to a OHCI list. We match anything that + is > 32ms to the 32ms interval list. The 32ms list is list 0, 16ms list is 1 ... + the 1ms list is number 5. */ + interval = endpoint -> ux_endpoint_descriptor.bInterval; + interval_index = 0x10; + interval_ohci = 1; + + /* Do a sanity check if the frequency is 0. That should not happen, so treat it as 1. */ + if (interval == 0) + { + + interval = 1; + } + + /* If the frequency is beyond the OHCI framework, make it the maximum of 32. */ + if (interval >= 32) + { + + interval_ohci = 0; + } + else + { + + /* We parse the interval from the high bits. This gives us the first power of 2 entry in the tree. */ + while (interval_index != 0) + { + + /* When we find the first bit of the interval the current value of interval_ohci is set to the the list index. */ + if (interval & interval_index) + break; + + /* Go down the tree one entry. */ + interval_ohci++; + + /* And shift the bit of the device interval to check. */ + interval_index = interval_index >> 1; + } + } + + /* Now we need to scan the list of eds from the lowest load entry until we reach the + appropriate interval node. The depth index is the interval OHCI value and the 1st + entry is pointed by the ED list entry. */ + while (interval_ohci--) + { + + ed_list = _ux_utility_virtual_address(ed_list -> ux_ohci_ed_next_ed); + while (!(ed_list -> ux_ohci_ed_dw0 & UX_OHCI_ED_SKIP)) + ed_list = _ux_utility_virtual_address(ed_list -> ux_ohci_ed_next_ed); + } + + /* We found the node entry of the ED pointer that will be the anchor for this interrupt + endpoint. Now we attach this endpoint to the anchor and rebuild the chain. */ + next_ed = ed_list -> ux_ohci_ed_next_ed; + + /* Check for end of tree which happens for devices with interval of 1. In this case + there might not be a next_ed. */ + if (next_ed != UX_NULL) + next_ed -> ux_ohci_ed_previous_ed = ed; + ed -> ux_ohci_ed_next_ed = _ux_utility_physical_address(next_ed); + ed -> ux_ohci_ed_previous_ed = ed_list; + ed_list -> ux_ohci_ed_next_ed = _ux_utility_physical_address(ed); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_interrupt_handler.c b/common/usbx_host_controllers/src/ux_hcd_ohci_interrupt_handler.c new file mode 100644 index 0000000..c1877ed --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_interrupt_handler.c @@ -0,0 +1,179 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_interrupt_handler PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the interrupt handler for the OHCI interrupts. */ +/* Normally an interrupt occurs from the controller when there is */ +/* either a EOF signal and there has been transfers within the frame */ +/* or when there is a change on one of the downstream ports. */ +/* */ +/* All we need to do in the ISR is scan the controllers to find out */ +/* which one has issued a IRQ. If there is work to do for this */ +/* controller we need to wake up the corresponding thread to take */ +/* care of the job. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_register_read Read OHCI register */ +/* _ux_hcd_ohci_register_write Write OHCI register */ +/* _ux_utility_semaphore_put Put semaphore */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX Interrupt Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ohci_interrupt_handler(VOID) +{ + +UINT hcd_index; +UX_HCD *hcd; +UX_HCD_OHCI *hcd_ohci; +ULONG ohci_register = 0; +ULONG ohci_register_port_status; +ULONG root_hub_thread_wakeup = 0; +ULONG port_index; + + + /* We need to parse the controller driver table to find all controllers that + registered as OHCI. */ + for (hcd_index = 0; hcd_index < _ux_system_host -> ux_system_host_registered_hcd; hcd_index++) + { + + /* Check type of controller. */ + if (_ux_system_host -> ux_system_host_hcd_array[hcd_index].ux_hcd_controller_type == UX_OHCI_CONTROLLER) + { + + /* Get the pointers to the generic HCD and OHCI specific areas. */ + hcd = &_ux_system_host -> ux_system_host_hcd_array[hcd_index]; + hcd_ohci = (UX_HCD_OHCI *) hcd -> ux_hcd_controller_hardware; + + /* Check if the controller is operational, if not, skip it. */ + if (hcd -> ux_hcd_status == UX_HCD_STATUS_OPERATIONAL) + { + + /* We get the current interrupt status for this controller. */ + ohci_register = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_INTERRUPT_STATUS); + + /* Examine the source of interrupts. */ + if (ohci_register & OHCI_HC_INT_WDH) + { + + /* We have some transferred EDs in the done queue. The controller thread needs + to wake up and process them. */ + hcd_ohci -> ux_hcd_ohci_done_head = hcd_ohci -> ux_hcd_ohci_hcca -> ux_hcd_ohci_hcca_done_head; + hcd_ohci -> ux_hcd_ohci_hcca -> ux_hcd_ohci_hcca_done_head = UX_NULL; + hcd -> ux_hcd_thread_signal++; + _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + + /* Since we have delayed the processing of the done queue to a thread. + We need to ensure the host controller will not overwrite the done + queue pointer. So we disable the WDH bit in the interrupt status + before we acknowledge the IRQ register. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_INTERRUPT_DISABLE, OHCI_HC_INT_WDH); + } + + if (ohci_register & OHCI_HC_INT_UE) + { + + /* The controller has issued a Unrecoverable Error signal. The controller will + be reset now, and we wake up the HCD thread. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_COMMAND_STATUS, OHCI_HC_CS_HCR); + hcd -> ux_hcd_thread_signal++; + hcd -> ux_hcd_status = UX_HCD_STATUS_DEAD; + _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_hcd_semaphore); + } + + if (ohci_register & OHCI_HC_INT_RHSC) + { + + /* The controller has issued a Root HUB status change signal. There may be one or more events + that caused this status change. Only device insertion/extraction are monitored here. */ + for (port_index = 0; port_index < hcd_ohci -> ux_hcd_ohci_nb_root_hubs; port_index++) + { + + /* Read the port status. */ + ohci_register_port_status = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index); + + /* Check for Connect Status Change signal. */ + if (ohci_register_port_status & OHCI_HC_PS_CSC) + { + /* Something happened on this port. Signal it to the root hub thread. */ + hcd -> ux_hcd_root_hub_signal[port_index]++; + + /* Memorize wake up signal. */ + root_hub_thread_wakeup ++; + } + + /* Clear the root hub interrupt signal. We do not turn off Port Reset status change here. + This will be done when the root hub requests a Port Reset. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index, (OHCI_HC_PS_CSC | OHCI_HC_PS_PESC | OHCI_HC_PS_PSSC | OHCI_HC_PS_OCIC )); + } + + /* We only wake up the root hub thread if there has been device insertion/extraction. */ + if (root_hub_thread_wakeup != 0) + _ux_utility_semaphore_put(&_ux_system_host -> ux_system_host_enum_semaphore); + } + } + + /* We have processed the interrupts for this controller, acknowledge them + so that the controller can continue to work. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_INTERRUPT_STATUS, ohci_register); + } + } +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_isochronous_endpoint_create.c b/common/usbx_host_controllers/src/ux_hcd_ohci_isochronous_endpoint_create.c new file mode 100644 index 0000000..988be0e --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_isochronous_endpoint_create.c @@ -0,0 +1,133 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_isochronous_endpoint_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates an isochronous endpoint. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_ed_obtain Obtain an OHCI ED */ +/* _ux_hcd_ohci_isochronous_td_obtain Obtain an OHCI TD */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_isochronous_endpoint_create(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint) +{ + +UX_HCD_OHCI_HCCA *ohci_hcca; +UX_DEVICE *device; +UX_OHCI_ED *ed; +UX_OHCI_ED *ed_list; +UX_OHCI_ISO_TD *td; + + + /* Get the pointer to the HCCA. */ + ohci_hcca = hcd_ohci -> ux_hcd_ohci_hcca; + + /* Obtain a ED for this new endpoint. This ED will live as long as + the endpoint is active and will be the container for the tds. */ + ed = _ux_hcd_ohci_ed_obtain(hcd_ohci); + if(ed==UX_NULL) + return(UX_NO_ED_AVAILABLE); + + /* Obtain a dummy isoch TD for terminating the ED transfer chain. */ + td = _ux_hcd_ohci_isochronous_td_obtain(hcd_ohci); + if (td == UX_NULL) + { + ed -> ux_ohci_ed_status = UX_UNUSED; + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the ED to the endpoint container. */ + endpoint -> ux_endpoint_ed = (VOID *) ed; + + /* Program the ED for subsequent transfers we need to set the following things: + + 1) Address of the device + 2) endpoint number + 3) speed (always full speed for iso) + 4) format of TD + 5) maximum packet size */ + + device = endpoint -> ux_endpoint_device; + ed -> ux_ohci_ed_dw0 = device -> ux_device_address | UX_OHCI_ED_ISOCHRONOUS | + ((ULONG) (endpoint -> ux_endpoint_descriptor.bEndpointAddress & ~UX_ENDPOINT_DIRECTION)) << 7 | + ((ULONG) (endpoint -> ux_endpoint_descriptor.wMaxPacketSize)) << 16; + + /* Hook the TD to both the tail and head of the ED. */ + ed -> ux_ohci_ed_tail_td = _ux_utility_physical_address(td); + ed -> ux_ohci_ed_head_td = _ux_utility_physical_address(td); + + /* Attach the ED to the 1ms interrupt tree. We scan the interrupt tree until the last entry. */ + ed_list = _ux_utility_virtual_address(ohci_hcca -> ux_hcd_ohci_hcca_ed[0]); + while (ed_list -> ux_ohci_ed_next_ed != UX_NULL) + ed_list = _ux_utility_virtual_address(ed_list -> ux_ohci_ed_next_ed); + + /* Now ed_list, points to the last ED, which is in the 1ms entry. */ + ed -> ux_ohci_ed_previous_ed = ed_list; + ed_list -> ux_ohci_ed_next_ed = _ux_utility_physical_address(ed); + + /* Return success. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_isochronous_td_obtain.c b/common/usbx_host_controllers/src/ux_hcd_ohci_isochronous_td_obtain.c new file mode 100644 index 0000000..dfb0690 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_isochronous_td_obtain.c @@ -0,0 +1,103 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_isochronous_td_obtain PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains a free TD from the isochronous TD list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI */ +/* */ +/* OUTPUT */ +/* */ +/* UX_OHCI_ISO_TD * Pointer to OHCI TD */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_set Set memory block */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_OHCI_ISO_TD *_ux_hcd_ohci_isochronous_td_obtain(UX_HCD_OHCI *hcd_ohci) +{ + +UX_OHCI_ISO_TD *td; +ULONG td_index; + + + /* Start the search from the beginning of the list. */ + td = hcd_ohci -> ux_hcd_ohci_iso_td_list; + for (td_index = 0; td_index < _ux_system_host -> ux_system_host_max_iso_td; td_index++) + { + + /* Check the TD status, a free TD is marked with the UNUSED flag. */ + if (td -> ux_ohci_iso_td_status == UX_UNUSED) + { + + /* The TD may have been used, so we reset all fields. */ + _ux_utility_memory_set(td, 0, sizeof(UX_OHCI_ISO_TD)); + + /* This TD is now marked as USED. */ + td -> ux_ohci_iso_td_status = UX_USED; + + /* Success, return the TD pointer. */ + return(td); + } + + /* Move to next TD. */ + td++; + } + + /* There is no available TD in the TD list. */ + return(UX_NULL); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_least_traffic_list_get.c b/common/usbx_host_controllers/src/ux_hcd_ohci_least_traffic_list_get.c new file mode 100644 index 0000000..1ee868a --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_least_traffic_list_get.c @@ -0,0 +1,133 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_least_traffic_list_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function return a pointer to the first ED in the periodic */ +/* tree that has the least traffic registered. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI */ +/* */ +/* OUTPUT */ +/* */ +/* UX_OHCI_ED * Pointer to OHCI ED */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_OHCI_ED *_ux_hcd_ohci_least_traffic_list_get(UX_HCD_OHCI *hcd_ohci) +{ + +UX_HCD_OHCI_HCCA *ohci_hcca; +UX_OHCI_ED *min_bandwidth_ed; +UX_OHCI_ED *begin_ed; +UX_OHCI_ED *ed; +UINT list_index; +ULONG min_bandwidth_used; +ULONG bandwidth_used; + + + /* Get the pointer to the HCCA. */ + ohci_hcca = hcd_ohci -> ux_hcd_ohci_hcca; + + /* Set the min bandwidth used to a arbitrary maximum value. */ + min_bandwidth_used = 0xffffffff; + + /* The first ED is the list candidate for now. */ + min_bandwidth_ed = _ux_utility_virtual_address(ohci_hcca -> ux_hcd_ohci_hcca_ed[0]); + + /* All list will be scanned. */ + for (list_index = 0; list_index < 32; list_index++) + { + + /* Reset the bandwidth for this list. */ + bandwidth_used = 0; + + /* Get the ED of the beginning of the list we parse now. */ + ed = _ux_utility_virtual_address(ohci_hcca -> ux_hcd_ohci_hcca_ed[list_index]); + + /* We keep track of the first ED for the current list. */ + begin_ed = ed; + + /* Parse the eds in the list. */ + while (ed -> ux_ohci_ed_next_ed != UX_NULL) + { + + /* Add to the bandwidth used the max packet size pointed by this ED. */ + bandwidth_used += (ed -> ux_ohci_ed_dw0 >> 16) & UX_OHCI_ED_MPS; + + /* Next ED. */ + ed = _ux_utility_virtual_address(ed -> ux_ohci_ed_next_ed); + } + + /* We have processed a list, check the bandwidth used by this list. + If this bandwidth is the minimum, we memorize the ED. */ + if (bandwidth_used < min_bandwidth_used) + { + + /* We have found a better list with a lower used bandwidth, + memorize the bandwidth for this list. */ + min_bandwidth_used = bandwidth_used; + + /* Memorize the begin ED for this list. */ + min_bandwidth_ed = begin_ed; + } + } + + /* Return the ED list with the lowest bandwidth. */ + return(min_bandwidth_ed); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_next_td_clean.c b/common/usbx_host_controllers/src/ux_hcd_ohci_next_td_clean.c new file mode 100644 index 0000000..dd185c0 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_next_td_clean.c @@ -0,0 +1,118 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_next_td_clean PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cleans all the tds attached to a ED. The end of the */ +/* TD chain is pointed by the tail TD. */ +/* */ +/* INPUT */ +/* */ +/* td Pointer to OHCI TD */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ohci_next_td_clean(UX_OHCI_TD *td) +{ + +UX_OHCI_ED *ed; +UX_OHCI_TD *head_td; +UX_OHCI_TD *tail_td; +ULONG value_td; +ULONG value_carry; + + + /* Obtain the pointer to the ED from the TD. */ + ed = td -> ux_ohci_td_ed; + + /* Ensure that the potential Carry bit is maintained in the head ED. */ + value_carry = (ULONG) _ux_utility_virtual_address(ed -> ux_ohci_ed_head_td) & UX_OHCI_ED_TOGGLE_CARRY; + + /* Ensure that the potential Halt bit is removed in the head ED. */ + value_td = (ULONG) _ux_utility_virtual_address(ed -> ux_ohci_ed_head_td) & UX_OHCI_ED_MASK_TD; + head_td = (UX_OHCI_TD *) _ux_utility_physical_address((VOID *) value_td); + + /* Remove all the tds from this ED and leave the head and tail pointing + to the dummy TD. */ + tail_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_tail_td); + + /* Free all tds attached to the ED. */ + while (head_td != tail_td) + { + + /* Mark the current head_td as free. */ + head_td -> ux_ohci_td_status = UX_UNUSED; + + /* Update the head TD with the next TD. */ + ed -> ux_ohci_ed_head_td = head_td -> ux_ohci_td_next_td; + + /* Now the new head_td is the next TD in the chain. */ + head_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_head_td); + } + + /* Restore the value carry for next transfers. */ + value_td = (ULONG) ed -> ux_ohci_ed_head_td; + value_td |= value_carry; + ed -> ux_ohci_ed_head_td = (UX_OHCI_TD *) value_td; + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_periodic_endpoint_destroy.c b/common/usbx_host_controllers/src/ux_hcd_ohci_periodic_endpoint_destroy.c new file mode 100644 index 0000000..f99fe04 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_periodic_endpoint_destroy.c @@ -0,0 +1,155 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_host_stack.h" +#include "ux_hcd_ohci.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_periodic_endpoint_destroy PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will destroy an interrupt or isochronous endpoint. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* endpoint Pointer to endpoint */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_delay_ms Delay ms */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_periodic_endpoint_destroy(UX_HCD_OHCI *hcd_ohci, UX_ENDPOINT *endpoint) +{ + +UX_OHCI_ED *ed; +UX_OHCI_ED *previous_ed; +UX_OHCI_ED *next_ed; +UX_OHCI_TD *tail_td; +UX_OHCI_TD *head_td; +ULONG value_td; + + + /* From the endpoint container fetch the OHCI ED descriptor. */ + ed = (UX_OHCI_ED*) endpoint -> ux_endpoint_ed; + + /* Check if this physical endpoint has been initialized properly! */ + if (ed == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* The endpoint may be active. If so, set the skip bit. */ + ed -> ux_ohci_ed_dw0 |= UX_OHCI_ED_SKIP; + + /* Wait for the controller to finish the current frame processing. */ + _ux_utility_delay_ms(1); + + /* Get the previous ED in the list for this ED. */ + previous_ed = ed -> ux_ohci_ed_previous_ed; + + /* Get the next ED in the list for this ED. */ + next_ed = ed -> ux_ohci_ed_next_ed; + + /* The previous ED points now to the ED after the ED we are removing. */ + previous_ed -> ux_ohci_ed_next_ed = next_ed; + + /* There may not be any next endpoint. But if there is one, link it + to the previous ED. */ + if (next_ed != UX_NULL) + + /* Update the previous ED pointer in the next ED. */ + next_ed -> ux_ohci_ed_previous_ed = previous_ed; + + /* We use the tail TD as a pointer to the Dummy TD. */ + tail_td = (UX_OHCI_TD *) _ux_utility_virtual_address(ed -> ux_ohci_ed_tail_td); + + /* Ensure that the potential Halt bit is removed in the head ED. */ + value_td = (ULONG) _ux_utility_virtual_address(ed -> ux_ohci_ed_head_td) & UX_OHCI_ED_MASK_TD; + head_td = (UX_OHCI_TD *) _ux_utility_physical_address((VOID *) value_td); + ed -> ux_ohci_ed_head_td = head_td; + + /* Remove all the tds from this ED and leave the head and tail pointing + to the dummy TD. */ + tail_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_tail_td); + + /* Free all tds attached to the ED */ + while (head_td != tail_td) + { + + /* Update the head TD with the next TD. */ + ed -> ux_ohci_ed_head_td = head_td -> ux_ohci_td_next_td; + + /* Mark the current head TD as free. */ + head_td -> ux_ohci_td_status = UX_UNUSED; + + /* Now the new head TD is the next TD in the chain. */ + head_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_head_td); + } + + /* We need to free the dummy TD that was attached to the ED. */ + tail_td -> ux_ohci_td_status = UX_UNUSED; + + /* Now we can safely make the ED free. */ + ed -> ux_ohci_ed_status = UX_UNUSED; + + /* Return success. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_periodic_tree_create.c b/common/usbx_host_controllers/src/ux_hcd_ohci_periodic_tree_create.c new file mode 100644 index 0000000..b193ac0 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_periodic_tree_create.c @@ -0,0 +1,147 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_periodic_tree_create PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates the periodic static tree for the interrupt */ +/* and isochronous eds. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_ed_obtain Obtain an ED */ +/* _ux_utility_physical_address Get physical address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_periodic_tree_create(UX_HCD_OHCI *hcd_ohci) +{ + +UX_HCD_OHCI_HCCA *ohci_hcca; +UX_OHCI_ED *ed; +UINT list_index; +UINT list_entries; +UINT current_list_entry; +UX_OHCI_ED *ed_list[32]; +UX_OHCI_ED *ed_start_list[32]; + + + /* We need the pointer to the HCCA. It contains the pointer to the first + 32 periodic entries. */ + ohci_hcca = hcd_ohci -> ux_hcd_ohci_hcca; + + /* Start with the 1st list - it has 32 entries. */ + list_entries = 32; + + /* Create each list one by one starting from the 32ms list. */ + for (list_index = 0; list_index < 6; list_index++) + { + + for (current_list_entry = 0; current_list_entry < list_entries;current_list_entry++) + { + + /* In each list, insert an static ED as the anchor. There should not + be any errors when obtaining a new ED, still we do a sanity check. */ + ed = _ux_hcd_ohci_ed_obtain(hcd_ohci); + if (ed == UX_NULL) + return(UX_NO_ED_AVAILABLE); + + /* Mark this anchor ED as static by putting it as SKIPPED, the OHCI + controller will not look into its tail and head list and will simply + jump to the next ED. */ + ed -> ux_ohci_ed_dw0 = UX_OHCI_ED_SKIP; + + /* Either we hook this new ED to the start list for further processing + or we hook it to the 2 successive entries in the previous list. */ + if (list_index == 0) + { + + ed_start_list[current_list_entry] = ed; + } + else + { + + ed_list[current_list_entry * 2] -> ux_ohci_ed_next_ed = _ux_utility_physical_address(ed); + ed_list[(current_list_entry * 2) + 1] -> ux_ohci_ed_next_ed = _ux_utility_physical_address(ed); + } + + /* Memorize this ED in the local list. We do this operation now, otherwise + we would erase the previous list eds. */ + ed_list[current_list_entry] = ed; + } + + /* Shift the number of entries in the next list by 1 (i.e. divide by 2). */ + list_entries = list_entries >> 1; + } + + /* The tree has been completed but the entries in the HCCA are in the wrong order. + We need to swap each entry according to the OHCI specified entry order list + so that we have a fair interval frequency for each periodic ED. The primary eds + are fetched from the start list, translated into physical addresses and stored + into the HCCA. */ + for (current_list_entry = 0; current_list_entry < 32; current_list_entry++) + { + + ed = ed_start_list[_ux_system_host_hcd_periodic_tree_entries[current_list_entry]]; + ohci_hcca -> ux_hcd_ohci_hcca_ed[current_list_entry] = _ux_utility_physical_address(ed); + } + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_port_disable.c b/common/usbx_host_controllers/src/ux_hcd_ohci_port_disable.c new file mode 100644 index 0000000..35f4bdb --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_port_disable.c @@ -0,0 +1,104 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_port_disable PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will disable a specific port attached to the root */ +/* HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* port_index Port index */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_register_read OHCI register read */ +/* _ux_hcd_ohci_register_write OHCI register write */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_port_disable(UX_HCD_OHCI *hcd_ohci, ULONG port_index) +{ + +ULONG ohci_register_port_status; + + + /* Check to see if this port is valid on this controller. */ + if (hcd_ohci -> ux_hcd_ohci_nb_root_hubs < port_index) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_INDEX_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_INDEX_UNKNOWN, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_PORT_INDEX_UNKNOWN); + } + + /* Read the port status for this port. */ + ohci_register_port_status = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index); + + /* Disable the port (CPE field). */ + ohci_register_port_status |= OHCI_HC_PS_CPE; + + /* Write the status back. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index, ohci_register_port_status); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_port_enable.c b/common/usbx_host_controllers/src/ux_hcd_ohci_port_enable.c new file mode 100644 index 0000000..377d572 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_port_enable.c @@ -0,0 +1,119 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_port_enable PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will enable a specific port attached to the root */ +/* HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* port_index Port index */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_register_read OHCI register read */ +/* _ux_hcd_ohci_register_write OHCI register write */ +/* _ux_utility_delay_ms Delay */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_port_enable(UX_HCD_OHCI *hcd_ohci, ULONG port_index) +{ + +ULONG ohci_register_port_status; + + + /* Check to see if this port is valid on this controller. */ + if (hcd_ohci -> ux_hcd_ohci_nb_root_hubs < port_index) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_INDEX_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_INDEX_UNKNOWN, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_PORT_INDEX_UNKNOWN); + } + + /* Ensure that the downstream port has a device attached. It is unnatural + to perform a port enable if there is no device. */ + ohci_register_port_status = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index); + + /* Check Device Connection Status. */ + if ((ohci_register_port_status & OHCI_HC_PS_CCS) == 0) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_NO_DEVICE_CONNECTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_NO_DEVICE_CONNECTED, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_NO_DEVICE_CONNECTED); + } + + /* Wait 50ms before we issue the command, otherwise some device do not answer! */ + _ux_utility_delay_ms(UX_PORT_ENABLE_WAIT); + + /* Write the command PES to this port. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index, OHCI_HC_PS_PES); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_port_reset.c b/common/usbx_host_controllers/src/ux_hcd_ohci_port_reset.c new file mode 100644 index 0000000..ab1cab9 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_port_reset.c @@ -0,0 +1,144 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_port_reset PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will reset a specific port attached to the root HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* port_index Port index */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_register_read OHCI register read */ +/* _ux_hcd_ohci_register_write OHCI register write */ +/* _ux_utility_delay_ms Delay */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_port_reset(UX_HCD_OHCI *hcd_ohci, ULONG port_index) +{ + +ULONG ohci_register_port_status; +UINT index_loop; + + + /* Check to see if this port is valid on this controller. */ + if (hcd_ohci -> ux_hcd_ohci_nb_root_hubs < port_index) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_INDEX_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_INDEX_UNKNOWN, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_PORT_INDEX_UNKNOWN); + } + + /* Ensure that the downstream port has a device attached. It is unnatural + to perform a port reset if there is no device. */ + ohci_register_port_status = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index); + + /* Check Device Connection Status. */ + if ((ohci_register_port_status & OHCI_HC_PS_CCS) == 0) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_NO_DEVICE_CONNECTED); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_NO_DEVICE_CONNECTED, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_NO_DEVICE_CONNECTED); + } + + /* Now we can safely issue a RESET command to this port. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index, OHCI_HC_PS_PRS); + + /* Normally, a port reset lasts for around 10ms. When the reset is completed + the controller will set the PRSC bit. We need to invert this bit by rewriting + a 1 to the PRSC field. */ + for (index_loop = 0; index_loop < UX_OHCI_PORT_RESET_RETRY; index_loop++) + { + + /* Perform the necessary delay to let the port reset properly. */ + _ux_utility_delay_ms(UX_OHCI_PORT_RESET_DELAY); + + /* Read the root HUB status change register. */ + ohci_register_port_status = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index); + + /* Reset completed? */ + if (ohci_register_port_status & OHCI_HC_PS_PRSC) + { + + /* The reset phase is complete, rewrite that bit to clear it and + return to the root HUB driver. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index, OHCI_HC_PS_PRSC); + + /* Return successful completion. */ + return(UX_SUCCESS); + } + } + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_RESET_FAILED, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + /* The reset failed! Inform the root HUB driver. This should not really happen in a 1.x controller. */ + return(UX_PORT_RESET_FAILED); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_port_resume.c b/common/usbx_host_controllers/src/ux_hcd_ohci_port_resume.c new file mode 100644 index 0000000..36a6d98 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_port_resume.c @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_port_resume PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will resume a specific port attached to the root */ +/* HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* port_index Port index */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_port_resume(UX_HCD_OHCI *hcd_ohci, UINT port_index) +{ + + return(UX_FUNCTION_NOT_SUPPORTED); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_port_status_get.c b/common/usbx_host_controllers/src/ux_hcd_ohci_port_status_get.c new file mode 100644 index 0000000..5a935d5 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_port_status_get.c @@ -0,0 +1,160 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_port_status_get PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will return the status for each port attached to the */ +/* root HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* port_index Port index */ +/* */ +/* OUTPUT */ +/* */ +/* port_status */ +/* */ +/* Status of the root HUB port with the following format: */ +/* */ +/* bit 0 device connection status */ +/* if 0 : no device connected */ +/* if 1 : device connected to the port */ +/* bit 1 port enable status */ +/* if 0 : port disabled */ +/* if 1 : port enabled */ +/* bit 2 port suspend status */ +/* if 0 : port is not suspended */ +/* if 1 : port is suspended */ +/* bit 3 port overcurrent status */ +/* if 0 : port has no overcurrent condition */ +/* if 1 : port has overcurrent condition */ +/* bit 4 port reset status */ +/* if 0 : port is not in reset */ +/* if 1 : port is in reset */ +/* bit 5 port power status */ +/* if 0 : port power is off */ +/* if 1 : port power is on */ +/* bit 6-7 device attached speed */ +/* if 00 : low speed device attached */ +/* if 01 : full speed device attached */ +/* if 10 : high speed device attached */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_register_read Read OHCI register */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_hcd_ohci_port_status_get(UX_HCD_OHCI *hcd_ohci, ULONG port_index) +{ + +ULONG ohci_register_port_status; +ULONG port_status; + + + /* Check to see if this port is valid on this controller */ + if (hcd_ohci -> ux_hcd_ohci_nb_root_hubs < port_index) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_PORT_INDEX_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_PORT_INDEX_UNKNOWN, port_index, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_PORT_INDEX_UNKNOWN); + } + + /* The port is valid, build the status mask for this port. This function + returns a controller agnostic bit field. */ + port_status = 0; + ohci_register_port_status = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index); + + /* Device Connection Status. */ + if (ohci_register_port_status & OHCI_HC_PS_CCS) + port_status |= UX_PS_CCS; + + /* Port Enable Status */ + if (ohci_register_port_status & OHCI_HC_PS_PES) + port_status |= UX_PS_PES; + + /* Port Suspend Status */ + if (ohci_register_port_status & OHCI_HC_PS_PSS) + port_status |= UX_PS_PSS; + + /* Port Overcurrent Status */ + if (ohci_register_port_status & OHCI_HC_PS_POCI) + port_status |= UX_PS_POCI; + + /* Port Reset Status */ + if (ohci_register_port_status & OHCI_HC_PS_PRS) + port_status |= UX_PS_PRS; + + /* Port Power Status */ + if (ohci_register_port_status & OHCI_HC_PS_PPS) + port_status |= UX_PS_PPS; + + /* Port Device Attached speed. This field is valid only if the CCS bit is active. + On OHCI, only low speed or full speed are available. */ + if (ohci_register_port_status & OHCI_HC_PS_CCS) + { + + if (ohci_register_port_status & OHCI_HC_PS_LSDA) + port_status |= UX_PS_DS_LS; + else + port_status |= UX_PS_DS_FS; + } + + /* Return port status. */ + return(port_status); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_port_suspend.c b/common/usbx_host_controllers/src/ux_hcd_ohci_port_suspend.c new file mode 100644 index 0000000..b51c494 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_port_suspend.c @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_port_suspend PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will suspend a specific port attached to the root */ +/* HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* port_index Port index */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_port_suspend(UX_HCD_OHCI *hcd_ohci, ULONG port_index) +{ + + return(UX_FUNCTION_NOT_SUPPORTED); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_power_down_port.c b/common/usbx_host_controllers/src/ux_hcd_ohci_power_down_port.c new file mode 100644 index 0000000..b52158c --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_power_down_port.c @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_power_down_port PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will power down a specific port attached to the */ +/* root HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* port_index Port index */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_power_down_port(UX_HCD_OHCI *hcd_ohci, ULONG port_index) +{ + + return(UX_FUNCTION_NOT_SUPPORTED); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_power_on_port.c b/common/usbx_host_controllers/src/ux_hcd_ohci_power_on_port.c new file mode 100644 index 0000000..40c4f81 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_power_on_port.c @@ -0,0 +1,76 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_power_on_port PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will power a specific port attached to the root HUB. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* port_index Port index */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_power_on_port(UX_HCD_OHCI *hcd_ohci, ULONG port_index) +{ + + return(UX_FUNCTION_NOT_SUPPORTED); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_power_root_hubs.c b/common/usbx_host_controllers/src/ux_hcd_ohci_power_root_hubs.c new file mode 100644 index 0000000..a85cbf8 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_power_root_hubs.c @@ -0,0 +1,148 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_power_root_hubs PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function powers individually or in gang mode the root HUBs */ +/* attached to the OHCI controller. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_register_read OHCI register read */ +/* _ux_hcd_ohci_register_write OHCI register write */ +/* _ux_utility_delay_ms Delay */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ohci_power_root_hubs(UX_HCD_OHCI *hcd_ohci) +{ + +ULONG ohci_register_a; +ULONG ohci_register_b; +ULONG ohci_register_port_status; +UINT port_index; + + + /* Read the RH descriptor A. This will tell us if ports are always powered or not. */ + ohci_register_a = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_RH_DESCRIPTOR_A); + if (ohci_register_a & OHCI_HC_RH_NPS) + return; + + /* Read the RH descriptor B. It will give us the characteristics of the root HUB. */ + ohci_register_b = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_RH_DESCRIPTOR_B); + + /* The ports must be power switched. There are 3 possibilities: + + 1) individual + 2) gang mode + 3) a combination of both + + The logic is as follows: + + If the PSM bit is not set, gang mode is forced and we use the global power (LPSC) command. + If PSM is set, each port is powered individually. + + BUT we also need to look into the PPCM field to check if there is any ports + that may still want to be powered by the global power command. If the bit for a port in + the mask is set, the power is applied by the local port command in the RH port status (PPS). */ + if (ohci_register_a & OHCI_HC_RH_PSM) + { + + /* Check the PPCM field to see if some existing ports need to be powered by the LPSC command. */ + for (port_index = 0; port_index < hcd_ohci -> ux_hcd_ohci_nb_root_hubs; port_index++) + { + + if ((ohci_register_b & (0x20000 << port_index)) == 0) + { + + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_RH_STATUS, OHCI_HC_RS_LPSC); + break; + } + } + + /* Ports have to be powered individually. This is done for each of the ports whose bit mask is + set in the PPCM field. */ + for (port_index = 0; port_index < hcd_ohci -> ux_hcd_ohci_nb_root_hubs; port_index++) + { + + if ((ohci_register_b & (0x20000 << port_index)) != 0) + { + + ohci_register_port_status = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index); + + ohci_register_port_status |= OHCI_HC_PS_PPS; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_RH_PORT_STATUS + port_index, ohci_register_port_status); + } + } + } + else + { + + /* Ports have to be powered all at the same time. */ + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_RH_STATUS, OHCI_HC_RS_LPSC); + } + + /* Wait for the power to be stable. the RH descriptor contains the value POTPGT. We multiply this value by 2 + and this is the number of milliseconds to wait for power to set. */ + _ux_utility_delay_ms(ohci_register_a >> (OHCI_HC_RH_POTPGT - 1)); + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_register_read.c b/common/usbx_host_controllers/src/ux_hcd_ohci_register_read.c new file mode 100644 index 0000000..23ae571 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_register_read.c @@ -0,0 +1,77 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_register_read PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads a register from the OHCI HCOR. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* ohci_register OHCI register to write to */ +/* */ +/* OUTPUT */ +/* */ +/* Value Read */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +ULONG _ux_hcd_ohci_register_read(UX_HCD_OHCI *hcd_ohci, ULONG ohci_register) +{ + + /* Return the value. */ + return(*(hcd_ohci -> ux_hcd_ohci_hcor + ohci_register)); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_register_write.c b/common/usbx_host_controllers/src/ux_hcd_ohci_register_write.c new file mode 100644 index 0000000..be3f026 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_register_write.c @@ -0,0 +1,81 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_register_write PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a register to the OHCI HCOR. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* ohci_register OHCI register to write to */ +/* value Value to write */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ohci_register_write(UX_HCD_OHCI *hcd_ohci, ULONG ohci_register, ULONG value) +{ + + /* Write to the register. */ + *(hcd_ohci -> ux_hcd_ohci_hcor + ohci_register) = value; + + /* Return to caller. */ + return; +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_regular_td_obtain.c b/common/usbx_host_controllers/src/ux_hcd_ohci_regular_td_obtain.c new file mode 100644 index 0000000..8f9b275 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_regular_td_obtain.c @@ -0,0 +1,117 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_regular_td_obtain PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function obtains a free TD from the regular TD list. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* */ +/* OUTPUT */ +/* */ +/* *UX_OHCI_TD Regular TD pointer */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_memory_set Set memory block */ +/* _ux_utility_mutex_on Get protection mutex */ +/* _ux_utility_mutex_off Release protection mutex */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UX_OHCI_TD *_ux_hcd_ohci_regular_td_obtain(UX_HCD_OHCI *hcd_ohci) +{ + +UX_OHCI_TD *td; +ULONG td_index; + + + /* Set the Mutex as this is a critical section. */ + _ux_utility_mutex_on(&_ux_system -> ux_system_mutex); + + /* Start the search from the beginning of the regular TD list. */ + td = hcd_ohci -> ux_hcd_ohci_td_list; + + for (td_index = 0; td_index < _ux_system_host -> ux_system_host_max_td; td_index++) + { + + /* Check the TD status, a free TD is marked with the UNUSED flag. */ + if (td -> ux_ohci_td_status == UX_UNUSED) + { + + /* The TD may have been used, so we reset all fields. */ + _ux_utility_memory_set(td, 0, sizeof(UX_OHCI_TD)); + + /* This TD is now marked as USED. */ + td -> ux_ohci_td_status = UX_USED; + + /* Release the protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* Return TD pointer - success! */ + return(td); + } + + /* Move to the next TD. */ + td++; + } + + /* There is no available TD in the TD list. */ + + /* Release protection. */ + _ux_utility_mutex_off(&_ux_system -> ux_system_mutex); + + /* Return NULL to caller. */ + return(UX_NULL); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_request_bulk_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ohci_request_bulk_transfer.c new file mode 100644 index 0000000..d65c88f --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_request_bulk_transfer.c @@ -0,0 +1,242 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_request_bulk_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a bulk transfer request. A bulk transfer */ +/* can be larger than the size of the OHCI buffer so it may be */ +/* required to chain multiple tds to accommodate this transfer */ +/* request. A bulk transfer is non blocking, so we return before the */ +/* transfer request is completed. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_register_read Read OHCI register */ +/* _ux_hcd_ohci_register_write Write OHCI register */ +/* _ux_hcd_ohci_regular_td_obtain Get regular TD */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_request_bulk_transfer(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_OHCI_TD *data_td; +UX_OHCI_TD *start_data_td; +UX_OHCI_TD *next_data_td; +UX_OHCI_TD *previous_td; +UX_OHCI_TD *tail_td; +UX_OHCI_ED *ed; +ULONG transfer_request_payload_length; +ULONG bulk_packet_payload_length; +UCHAR * data_pointer; +ULONG ohci_register; +ULONG zlp_flag; + + + /* Get the pointer to the Endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* Now get the physical ED attached to this endpoint. */ + ed = endpoint -> ux_endpoint_ed; + + /* Use the TD pointer by ed -> tail for the first TD of this transfer + and chain from this one on. */ + data_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_tail_td); + previous_td = data_td; + + /* Reset the first obtained data TD in case there is a TD shortage while building the list of tds. */ + start_data_td = 0; + + /* It may take more than one TD if the transfer_request length is more than the + maximum length for a OHCI TD (this is irrelevant of the MaxPacketSize value in + the endpoint descriptor). OHCI data payload has a maximum size of 4K. */ + transfer_request_payload_length = transfer_request -> ux_transfer_request_requested_length; + data_pointer = transfer_request -> ux_transfer_request_data_pointer; + + /* Check for ZLP condition. */ + if (transfer_request_payload_length == 0) + + /* We have a zlp condition. */ + zlp_flag = UX_TRUE; + else + + /* We do not have a zlp. */ + zlp_flag = UX_FALSE; + + /* Build all necessary TDs. */ + while ((transfer_request_payload_length != 0) || zlp_flag == UX_TRUE) + { + + /* Reset ZLP now. */ + zlp_flag = UX_FALSE; + + /* Check if we are exceeding the max payload. */ + if (transfer_request_payload_length > UX_OHCI_MAX_PAYLOAD) + + bulk_packet_payload_length = UX_OHCI_MAX_PAYLOAD; + else + + bulk_packet_payload_length = transfer_request_payload_length; + + /* IN transfer ? */ + if ((transfer_request -> ux_transfer_request_type&UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + + data_td -> ux_ohci_td_dw0 = UX_OHCI_TD_IN | UX_OHCI_TD_DEFAULT_DW0; + else + + data_td -> ux_ohci_td_dw0 = UX_OHCI_TD_OUT | UX_OHCI_TD_DEFAULT_DW0; + + /* Store the beginning of the buffer address in the TD. */ + data_td -> ux_ohci_td_cbp = _ux_utility_physical_address(data_pointer); + + /* Store the end buffer address in the TD. */ + data_td -> ux_ohci_td_be = data_td -> ux_ohci_td_cbp + bulk_packet_payload_length - 1; + + /* Update the length of the transfer for this TD. */ + data_td -> ux_ohci_td_length = bulk_packet_payload_length; + + /* Attach the endpoint and transfer request to the TD. */ + data_td -> ux_ohci_td_transfer_request = transfer_request; + data_td -> ux_ohci_td_ed = ed; + + /* Adjust the data payload length and the data payload pointer. */ + transfer_request_payload_length -= bulk_packet_payload_length; + data_pointer += bulk_packet_payload_length; + + /* Check if there will be another transaction. */ + if (transfer_request_payload_length != 0) + { + + /* Get a new TD to hook this payload. */ + data_td = _ux_hcd_ohci_regular_td_obtain(hcd_ohci); + + if (data_td == UX_NULL) + { + + /* If there was already a TD chain in progress, free it. */ + if (start_data_td != UX_NULL) + { + + data_td = start_data_td; + while(data_td) + { + + next_data_td = _ux_utility_virtual_address(data_td -> ux_ohci_td_next_td); + data_td -> ux_ohci_td_status = UX_UNUSED; + data_td = next_data_td; + } + } + + return(UX_NO_TD_AVAILABLE); + } + + /* the first obtained TD in the chain has to be remembered. */ + if (start_data_td == UX_NULL) + start_data_td = data_td; + + /* Attach this new TD to the previous one. */ + previous_td -> ux_ohci_td_next_td = _ux_utility_physical_address(data_td); + previous_td -> ux_ohci_td_next_td_transfer_request = data_td; + previous_td = data_td; + } + } + + /* At this stage, the Head and Tail in the ED are still the same and the OHCI controller + will skip this ED until we have hooked the new tail TD. */ + tail_td = _ux_hcd_ohci_regular_td_obtain(hcd_ohci); + if (tail_td == UX_NULL) + { + + /* If there was already a TD chain in progress, free it. */ + if (start_data_td != UX_NULL) + { + + data_td = start_data_td; + while(data_td) + { + + next_data_td = _ux_utility_virtual_address(data_td -> ux_ohci_td_next_td); + data_td -> ux_ohci_td_status = UX_UNUSED; + data_td = next_data_td; + } + } + + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the tail TD to the last data TD. */ + data_td -> ux_ohci_td_next_td = _ux_utility_physical_address(tail_td); + + /* Store the new tail TD. */ + ed -> ux_ohci_ed_tail_td = _ux_utility_physical_address(tail_td); + + /* Now, we must tell the OHCI controller that there is something in the + bulk queue. */ + ohci_register = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_COMMAND_STATUS); + ohci_register |= OHCI_HC_CS_BLF; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_COMMAND_STATUS, ohci_register); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_request_control_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ohci_request_control_transfer.c new file mode 100644 index 0000000..a7900b9 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_request_control_transfer.c @@ -0,0 +1,273 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_request_control_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs a control transfer from a transfer request. */ +/* The USB control transfer is in 3 phases (setup, data, status). */ +/* This function will chain all phases of the control sequence before */ +/* setting the OHCI endpoint as a candidate for transfer. */ +/* */ +/* The maximum aggregated size of a data payload in OHCI is 4K. We */ +/* are assuming that this size will be sufficient to contain the */ +/* control packet. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_register_read Read OHCI register */ +/* _ux_hcd_ohci_register_write Write OHCI register */ +/* _ux_hcd_ohci_regular_td_obtain Get regular TD */ +/* _ux_host_stack_transfer_request_abort Abort transfer request */ +/* _ux_utility_memory_allocate Allocate memory block */ +/* _ux_utility_memory_free Release memory block */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_semaphore_get Get semaphore */ +/* _ux_utility_short_put Write 16-bit value */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_request_control_transfer(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request) +{ + +UX_DEVICE *device; +UX_ENDPOINT *endpoint; +UCHAR * setup_request; +UX_OHCI_ED *ed; +UX_OHCI_TD *setup_td; +UX_OHCI_TD *chain_td; +UX_OHCI_TD *data_td; +UX_OHCI_TD *tail_td; +UX_OHCI_TD *status_td; +ULONG ohci_register; +UINT status; + + + /* Get the pointer to the Endpoint and the Device. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + device = endpoint -> ux_endpoint_device; + + /* Now get the physical ED attached to this endpoint. */ + ed = endpoint -> ux_endpoint_ed; + + /* Build the SETUP packet (phase 1 of the control transfer). */ + setup_request = _ux_utility_memory_allocate(UX_NO_ALIGN, UX_CACHE_SAFE_MEMORY, UX_SETUP_SIZE); + if (setup_request == UX_NULL) + return(UX_MEMORY_INSUFFICIENT); + + *setup_request = transfer_request -> ux_transfer_request_function; + *(setup_request + UX_SETUP_REQUEST_TYPE) = transfer_request -> ux_transfer_request_type; + *(setup_request + UX_SETUP_REQUEST) = transfer_request -> ux_transfer_request_function; + _ux_utility_short_put(setup_request + UX_SETUP_VALUE, transfer_request -> ux_transfer_request_value); + _ux_utility_short_put(setup_request + UX_SETUP_INDEX, transfer_request -> ux_transfer_request_index); + _ux_utility_short_put(setup_request + UX_SETUP_LENGTH, (USHORT) transfer_request -> ux_transfer_request_requested_length); + + /* Set the ED address and MPS values since they may have changed. + The ED direction will be set from the TD. */ + ed -> ux_ohci_ed_dw0 = device -> ux_device_address | ((ULONG) endpoint -> ux_endpoint_descriptor.bEndpointAddress << 7) | + ((ULONG) endpoint -> ux_endpoint_descriptor.wMaxPacketSize << 16); + + /* Refresh the speed. */ + if (device -> ux_device_speed == UX_LOW_SPEED_DEVICE) + ed -> ux_ohci_ed_dw0 |= UX_OHCI_ED_LOW_SPEED; + + /* Use the TD pointer by ed -> tail for our setup TD and chain from this one on. */ + setup_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_tail_td); + setup_td -> ux_ohci_td_dw0 = UX_OHCI_TD_DEFAULT_DW0 | UX_OHCI_TD_DATA0 | UX_OHCI_TD_R; + setup_td -> ux_ohci_td_cbp = _ux_utility_physical_address(setup_request); + setup_td -> ux_ohci_td_be = setup_td -> ux_ohci_td_cbp + UX_SETUP_SIZE - 1; + chain_td = setup_td; + + /* Attach the endpoint and transfer request to the TD. */ + setup_td -> ux_ohci_td_transfer_request = transfer_request; + setup_td -> ux_ohci_td_ed = ed; + + /* Mark the TD with the SETUP phase. */ + setup_td -> ux_ohci_td_status |= UX_OHCI_TD_SETUP_PHASE; + + /* Check if there is a data phase, if not jump to status phase. */ + data_td = UX_NULL; + if (transfer_request -> ux_transfer_request_requested_length != 0) + { + + data_td = _ux_hcd_ohci_regular_td_obtain(hcd_ohci); + if (data_td == UX_NULL) + { + + _ux_utility_memory_free(setup_request); + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the endpoint and transfer request to the TD. */ + data_td -> ux_ohci_td_transfer_request = transfer_request; + data_td -> ux_ohci_td_ed = ed; + + /* Mark the TD with the DATA phase. */ + data_td -> ux_ohci_td_status |= UX_OHCI_TD_DATA_PHASE; + + /* Program the control bits of the TD. */ + if ((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + + data_td -> ux_ohci_td_dw0 = UX_OHCI_TD_DEFAULT_DW0 | UX_OHCI_TD_IN | UX_OHCI_TD_DATA1 | UX_OHCI_TD_R; + else + + data_td -> ux_ohci_td_dw0 = UX_OHCI_TD_DEFAULT_DW0 | UX_OHCI_TD_OUT | UX_OHCI_TD_DATA1 | UX_OHCI_TD_R; + + /* Attach the CBP and BE values to the TD. */ + data_td -> ux_ohci_td_cbp = _ux_utility_physical_address(transfer_request -> ux_transfer_request_data_pointer); + data_td -> ux_ohci_td_be = data_td -> ux_ohci_td_cbp + transfer_request -> ux_transfer_request_requested_length - 1; + + /* Update the length of the transfer for this TD. */ + data_td -> ux_ohci_td_length = transfer_request -> ux_transfer_request_requested_length; + + /* Chain the TD. */ + chain_td -> ux_ohci_td_next_td = _ux_utility_physical_address(data_td); + chain_td = data_td; + } + + /* Now, program the status phase. */ + status_td = _ux_hcd_ohci_regular_td_obtain(hcd_ohci); + if (status_td == UX_NULL) + { + + _ux_utility_memory_free(setup_request); + if (data_td != UX_NULL) + data_td -> ux_ohci_td_status = UX_UNUSED; + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the endpoint and transfer request to the TD. */ + status_td -> ux_ohci_td_transfer_request = transfer_request; + status_td -> ux_ohci_td_ed = ed; + + /* Mark the TD with the STATUS phase. */ + status_td -> ux_ohci_td_status |= UX_OHCI_TD_STATUS_PHASE; + + /* The direction of the status phase is IN if data phase is OUT and + vice versa. */ + if ((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + + status_td -> ux_ohci_td_dw0 = UX_OHCI_TD_DEFAULT_DW0 | UX_OHCI_TD_OUT | UX_OHCI_TD_DATA1; + else + + status_td -> ux_ohci_td_dw0 = UX_OHCI_TD_DEFAULT_DW0 | UX_OHCI_TD_IN | UX_OHCI_TD_DATA1; + + /* No data payload for the status phase. */ + status_td -> ux_ohci_td_cbp = 0; + status_td -> ux_ohci_td_be = 0; + + /* Hook the status phase to the previous TD. */ + chain_td -> ux_ohci_td_next_td = _ux_utility_physical_address(status_td); + + /* Since we have consumed out tail TD for the setup packet, we must get another + one and hook it to the ED's tail. */ + tail_td = _ux_hcd_ohci_regular_td_obtain(hcd_ohci); + if (tail_td == UX_NULL) + { + + _ux_utility_memory_free(setup_request); + if (data_td != UX_NULL) + data_td -> ux_ohci_td_status = UX_UNUSED; + status_td -> ux_ohci_td_status = UX_UNUSED; + return(UX_NO_TD_AVAILABLE); + } + + /* Hook the new TD to the status TD. */ + status_td -> ux_ohci_td_next_td = _ux_utility_physical_address(tail_td); + + /* At this stage, the Head and Tail in the ED are still the same and + the OHCI controller will skip this ED until we have hooked the new + tail TD. */ + ed -> ux_ohci_ed_tail_td = _ux_utility_physical_address(tail_td); + + /* Now, we must tell the OHCI controller that there is something in the + control queue. */ + ohci_register = _ux_hcd_ohci_register_read(hcd_ohci, OHCI_HC_COMMAND_STATUS); + ohci_register |= OHCI_HC_CS_CLF; + _ux_hcd_ohci_register_write(hcd_ohci, OHCI_HC_COMMAND_STATUS, ohci_register); + + /* Wait for the completion of the transfer request. */ + status = _ux_utility_semaphore_get(&transfer_request -> ux_transfer_request_semaphore, MS_TO_TICK(UX_CONTROL_TRANSFER_TIMEOUT)); + + /* If the semaphore did not succeed we probably have a time out. */ + if (status != UX_SUCCESS) + { + + /* All transfers pending need to abort. There may have been a partial transfer. */ + _ux_host_stack_transfer_request_abort(transfer_request); + + /* There was an error, return to the caller. */ + transfer_request -> ux_transfer_request_completion_code = UX_TRANSFER_TIMEOUT; + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_TRANSFER_TIMEOUT); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_TRANSFER_TIMEOUT, transfer_request, 0, 0, UX_TRACE_ERRORS, 0, 0) + + } + + /* Free the resources. */ + _ux_utility_memory_free(setup_request); + + /* Return the completion status. */ + return(transfer_request -> ux_transfer_request_completion_code); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_request_interupt_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ohci_request_interupt_transfer.c new file mode 100644 index 0000000..a981267 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_request_interupt_transfer.c @@ -0,0 +1,135 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_request_interrupt_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs an interrupt transfer request. An interrupt */ +/* transfer can only be as large as the MaxpacketField in the */ +/* endpoint descriptor. This was verified at a higher layer and does */ +/* not need to be reverified here. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_regular_td_obtain Get regular TD */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_request_interrupt_transfer(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_OHCI_ED *ed; +UX_OHCI_TD *data_td; +UX_OHCI_TD *tail_td; + + + /* Get the pointer to the Endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* Now get the physical ED attached to this endpoint. */ + ed = endpoint -> ux_endpoint_ed; + + /* Use the TD pointer by ed -> tail for the first TD of this transfer + and chain from this one on. */ + data_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_tail_td); + + /* Set the direction of the transfer. In USB 1.0, the direction of the Interrupt pipe could + only be HOST to DEVICE. In 1.1 bidirectional interrupt endpoints can be allowed. The + direction was checked when the endpoint was initialized. */ + if ((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + + data_td -> ux_ohci_td_dw0 = UX_OHCI_TD_IN | UX_OHCI_TD_DEFAULT_DW0; + else + + data_td -> ux_ohci_td_dw0 = UX_OHCI_TD_OUT | UX_OHCI_TD_DEFAULT_DW0; + + /* Store the beginning of the buffer address in the TD. */ + data_td -> ux_ohci_td_cbp = _ux_utility_physical_address(transfer_request -> ux_transfer_request_data_pointer); + + /* Store the end buffer address in the TD. */ + data_td -> ux_ohci_td_be = data_td -> ux_ohci_td_cbp + transfer_request -> ux_transfer_request_requested_length - 1; + + /* Update the length of the transfer for this TD. */ + data_td -> ux_ohci_td_length = transfer_request -> ux_transfer_request_requested_length; + + /* Attach the endpoint and transfer_request to the TD. */ + data_td -> ux_ohci_td_transfer_request = transfer_request; + data_td -> ux_ohci_td_ed = ed; + + /* At this stage, the Head and Tail in the ED are still the same and the OHCI controller + will skip this ED until we have hooked the new tail TD. */ + tail_td = _ux_hcd_ohci_regular_td_obtain(hcd_ohci); + if (tail_td == UX_NULL) + return(UX_NO_TD_AVAILABLE); + + /* Attach the tail TD to the last data TD. */ + data_td -> ux_ohci_td_next_td = _ux_utility_physical_address(tail_td); + + /* Store the new tail TD. */ + ed -> ux_ohci_ed_tail_td = _ux_utility_physical_address(tail_td); + + /* There is no need to wake up the ohci controller on this transfer + since periodic transactions will be picked up when the interrupt + tree is scanned. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_request_isochronous_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ohci_request_isochronous_transfer.c new file mode 100644 index 0000000..9000e0c --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_request_isochronous_transfer.c @@ -0,0 +1,246 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_request_isochronous_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs an isochronous transfer request. This */ +/* function does not support multiple packets per TD as there can be */ +/* issues with packets crossing 4K pages. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_isochronous_td_obtain Get isochronous TD */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_request_isochronous_transfer(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_OHCI_ISO_TD *data_td; +UX_OHCI_ISO_TD *start_data_td; +UX_OHCI_ISO_TD *next_data_td; +UX_OHCI_ISO_TD *previous_td; +UX_OHCI_ISO_TD *tail_td; +UX_OHCI_ED *ed; +ULONG transfer_request_payload_length; +ULONG isoch_packet_payload_length; +UCHAR * data_pointer; +ULONG current_frame_number; + + + /* Get the pointer to the Endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* Now get the physical ED attached to this endpoint. */ + ed = endpoint -> ux_endpoint_ed; + + /* Reset the MPS value of the ED. */ + ed -> ux_ohci_ed_dw0 &= UX_OHCI_ED_MPS; + + /* If the transfer request specifies a max packet length other than the endpoint + size, we force the transfer request value into the endpoint. */ + if (transfer_request -> ux_transfer_request_packet_length == 0) + transfer_request -> ux_transfer_request_packet_length = (ULONG) endpoint -> ux_endpoint_descriptor.wMaxPacketSize; + + /* Set the packet length in the ED. */ + ed -> ux_ohci_ed_dw0 |= transfer_request -> ux_transfer_request_packet_length << 16; + isoch_packet_payload_length = transfer_request -> ux_transfer_request_packet_length; + + /* Use the TD pointer by ed -> tail for the first TD of this transfer + and chain from this one on. */ + data_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_tail_td); + previous_td = data_td; + + /* Reset the first obtained data TD in case there is a TD shortage while building the list of TDs. */ + start_data_td = UX_NULL; + + /* Calculate the frame number to be used to send this payload. If there are no current transfers, + we take the current frame number and add a safety value (2-5) to it. If here is pending transactions, + we use the frame number stored in the transfer request. */ + if (ed -> ux_ohci_ed_tail_td == ed -> ux_ohci_ed_head_td) + { + + current_frame_number = hcd_ohci -> ux_hcd_ohci_hcca -> ux_hcd_ohci_hcca_frame_number + UX_OHCI_FRAME_DELAY; + ed -> ux_ohci_ed_frame = current_frame_number; + } + else + current_frame_number = ed -> ux_ohci_ed_frame; + + /* Load the start buffer address and URB length to split the URB in multiple TD transfer. */ + transfer_request_payload_length = transfer_request -> ux_transfer_request_requested_length; + data_pointer = transfer_request -> ux_transfer_request_data_pointer; + + while (transfer_request_payload_length != 0) + { + + /* Set the default CC value. Default is 1 packet per TD frame. */ + data_td -> ux_ohci_iso_td_dw0 = UX_OHCI_TD_DEFAULT_DW0; + + /* Set the direction. In Iso, this is done at the ED level. */ + if ((transfer_request -> ux_transfer_request_type & UX_REQUEST_DIRECTION) == UX_REQUEST_IN) + + ed -> ux_ohci_ed_dw0 |= UX_OHCI_ED_IN; + else + ed -> ux_ohci_ed_dw0 |= UX_OHCI_ED_OUT; + + /* Set the frame number. */ + data_td -> ux_ohci_iso_td_dw0 |= (USHORT) current_frame_number; + + /* The buffer address is divided into a page and an offset. */ + data_td -> ux_ohci_iso_td_bp0 = _ux_utility_physical_address((VOID *)((ULONG) data_pointer & UX_OHCI_ISO_TD_BASE)); + data_td -> ux_ohci_iso_td_offset_psw[0] = (USHORT)((ULONG) _ux_utility_physical_address(data_pointer) & UX_OHCI_ISO_TD_OFFSET); + + /* Set the condition code for the current packet. */ + data_td -> ux_ohci_iso_td_offset_psw[0] |= (USHORT) UX_OHCI_ISO_TD_PSW_CC; + + /* Program the end address of the buffer. */ + data_td -> ux_ohci_iso_td_be = ((UCHAR *) _ux_utility_physical_address(data_pointer)) + isoch_packet_payload_length - 1; + + /* Update the length of the transfer for this TD. */ + data_td -> ux_ohci_iso_td_length = isoch_packet_payload_length; + + /* Attach the endpoint and transfer request to the TD. */ + data_td -> ux_ohci_iso_td_transfer_request = transfer_request; + data_td -> ux_ohci_iso_td_ed = ed; + + /* Adjust the data payload length and the data payload pointer. */ + transfer_request_payload_length -= isoch_packet_payload_length; + data_pointer += isoch_packet_payload_length; + + /* Prepare the next frame for the next TD in advance. */ + current_frame_number++; + + /* Check if there will be another transaction. */ + if (transfer_request_payload_length != 0) + { + + /* Get a new TD to hook this payload. */ + data_td = _ux_hcd_ohci_isochronous_td_obtain(hcd_ohci); + if (data_td == UX_NULL) + { + + /* If there was already a TD chain in progress, free it. */ + if (start_data_td != UX_NULL) + { + + data_td = start_data_td; + while(data_td) + { + + next_data_td = _ux_utility_virtual_address(data_td -> ux_ohci_iso_td_next_td); + data_td -> ux_ohci_iso_td_status = UX_UNUSED; + data_td = next_data_td; + } + } + + return(UX_NO_TD_AVAILABLE); + } + + /* the first obtained TD in the chain has to be remembered. */ + if (start_data_td == UX_NULL) + start_data_td = data_td; + + /* Attach this new TD to the previous one. */ + previous_td -> ux_ohci_iso_td_next_td = _ux_utility_physical_address(data_td); + previous_td = data_td; + } + } + + /* Memorize the next frame number for this ED. */ + ed -> ux_ohci_ed_frame = current_frame_number; + + /* At this stage, the Head and Tail in the ED are still the same and + the OHCI controller will skip this ED until we have hooked the new + tail TD. */ + tail_td = _ux_hcd_ohci_isochronous_td_obtain(hcd_ohci); + if (tail_td == UX_NULL) + { + + /* If there was already a TD chain in progress, free it. */ + if (start_data_td != UX_NULL) + { + + data_td = start_data_td; + while (data_td) + { + + next_data_td = _ux_utility_virtual_address(data_td -> ux_ohci_iso_td_next_td); + data_td -> ux_ohci_iso_td_status = UX_UNUSED; + data_td = next_data_td; + } + } + + return(UX_NO_TD_AVAILABLE); + } + + /* Attach the tail TD to the last data TD. */ + data_td -> ux_ohci_iso_td_next_td = _ux_utility_physical_address(tail_td); + + /* Adjust the ED tail pointer, the controller can now start this transfer + at the chosen frame number. */ + ed -> ux_ohci_ed_tail_td = _ux_utility_physical_address(tail_td); + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_request_transfer.c b/common/usbx_host_controllers/src/ux_hcd_ohci_request_transfer.c new file mode 100644 index 0000000..a962860 --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_request_transfer.c @@ -0,0 +1,129 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_request_transfer PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the handler for all the transactions on the USB. */ +/* The transfer request passed as parameter contains the endpoint and */ +/* the device descriptors in addition to the type of transaction to */ +/* be executed. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_hcd_ohci_request_bulk_transfer Start bulk transfer */ +/* _ux_hcd_ohci_request_control_transfer Start control transfer */ +/* _ux_hcd_ohci_request_interrupt_transfer Start interrupt transfer */ +/* _ux_hcd_ohci_request_isochronous_transfer Start isochronous transfer*/ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_request_transfer(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UINT status; + + + /* Get the pointer to the Endpoint. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* We reset the actual length field of the transfer request as a safety measure. */ + transfer_request -> ux_transfer_request_actual_length = 0; + + /* Isolate the endpoint type and route the transfer request. */ + switch ((endpoint -> ux_endpoint_descriptor.bmAttributes) & UX_MASK_ENDPOINT_TYPE) + { + + case UX_CONTROL_ENDPOINT: + + /* Control transfer. */ + status = _ux_hcd_ohci_request_control_transfer(hcd_ohci, transfer_request); + break; + + + case UX_BULK_ENDPOINT: + + /* Bulk transfer. */ + status = _ux_hcd_ohci_request_bulk_transfer(hcd_ohci, transfer_request); + break; + + + case UX_INTERRUPT_ENDPOINT: + + /* Interrupt transfer. */ + status = _ux_hcd_ohci_request_interrupt_transfer(hcd_ohci, transfer_request); + break; + + + case UX_ISOCHRONOUS_ENDPOINT: + + /* Isochronous transfer. */ + status = _ux_hcd_ohci_request_isochronous_transfer(hcd_ohci, transfer_request); + break; + + } + + /* Note that it is physically impossible to have a wrong endpoint type here + so no error checking! */ + + /* Return completion status. */ + return(status); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_abort.c b/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_abort.c new file mode 100644 index 0000000..61c7a9e --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_abort.c @@ -0,0 +1,147 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_transfer_abort PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function will abort transactions attached to a transfer */ +/* request. */ +/* */ +/* INPUT */ +/* */ +/* hcd_ohci Pointer to OHCI controller */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* Completion Status */ +/* */ +/* CALLS */ +/* */ +/* _ux_utility_delay_ms Delay */ +/* _ux_utility_physical_address Get physical address */ +/* _ux_utility_virtual_address Get virtual address */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_hcd_ohci_transfer_abort(UX_HCD_OHCI *hcd_ohci, UX_TRANSFER *transfer_request) +{ + +UX_ENDPOINT *endpoint; +UX_OHCI_ED *ed; +UX_OHCI_TD *head_td; +UX_OHCI_TD *tail_td; +ULONG value_td; +ULONG value_carry; + + + /* Get the pointer to the endpoint associated with the transfer request. */ + endpoint = (UX_ENDPOINT *) transfer_request -> ux_transfer_request_endpoint; + + /* From the endpoint container, get the address of the physical endpoint. */ + ed = (UX_OHCI_ED *) endpoint -> ux_endpoint_ed; + + /* Check if this physical endpoint has been initialized properly! */ + if (ed == UX_NULL) + { + + /* Error trap. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_HCD, UX_ENDPOINT_HANDLE_UNKNOWN); + + /* If trace is enabled, insert this event into the trace buffer. */ + UX_TRACE_IN_LINE_INSERT(UX_TRACE_ERROR, UX_ENDPOINT_HANDLE_UNKNOWN, endpoint, 0, 0, UX_TRACE_ERRORS, 0, 0) + + return(UX_ENDPOINT_HANDLE_UNKNOWN); + } + + /* The endpoint may be active. If so, set the skip bit. */ + ed -> ux_ohci_ed_dw0 |= UX_OHCI_ED_SKIP; + + /* Wait for the controller to finish the current frame processing. */ + _ux_utility_delay_ms(1); + + /* Ensure that the potential Carry bit is maintained in the head ED. */ + value_carry = (ULONG) _ux_utility_virtual_address(ed -> ux_ohci_ed_head_td) & UX_OHCI_ED_TOGGLE_CARRY; + + /* Ensure that the potential Halt bit is removed in the head ED. */ + value_td = (ULONG) _ux_utility_virtual_address(ed -> ux_ohci_ed_head_td) & UX_OHCI_ED_MASK_TD; + head_td = (UX_OHCI_TD *) _ux_utility_physical_address((VOID *) value_td); + ed -> ux_ohci_ed_head_td = head_td; + + /* Remove all the tds from this ED and leave the head and tail pointing + to the dummy TD. */ + tail_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_tail_td); + + /* Free all tds attached to the ED */ + while (head_td != tail_td) + { + + /* Update the head TD with the next TD. */ + ed -> ux_ohci_ed_head_td = head_td -> ux_ohci_td_next_td; + + /* Mark the current head TD as free. */ + head_td -> ux_ohci_td_status = UX_UNUSED; + + /* Now the new head TD is the next TD in the chain. */ + head_td = _ux_utility_virtual_address(ed -> ux_ohci_ed_head_td); + } + + /* Restore the value carry for next transfers. */ + value_td = (ULONG) ed -> ux_ohci_ed_head_td; + value_td |= value_carry; + ed -> ux_ohci_ed_head_td = (UX_OHCI_TD *) value_td; + + /* Remove the reset bit in the ED. */ + ed -> ux_ohci_ed_dw0 &= ~UX_OHCI_ED_SKIP; + + /* Return successful completion. */ + return(UX_SUCCESS); +} + diff --git a/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_request_process.c b/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_request_process.c new file mode 100644 index 0000000..ae7bb7a --- /dev/null +++ b/common/usbx_host_controllers/src/ux_hcd_ohci_transfer_request_process.c @@ -0,0 +1,91 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** OHCI Controller Driver */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/* Include necessary system files. */ + +#define UX_SOURCE_CODE + +#include "ux_api.h" +#include "ux_hcd_ohci.h" +#include "ux_host_stack.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_hcd_ohci_transfer_request_process PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function process the transfer request that was completed */ +/* either with success or because of a partial transmission or */ +/* because of an error. The transfer request descriptor tells us what */ +/* to do with it, either put a semaphore to the caller or invoke a */ +/* completion routine. If a completion routine is specified, the */ +/* routine is called and no semaphore is put. */ +/* */ +/* INPUT */ +/* */ +/* transfer_request Pointer to transfer request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* (ux_transfer_request_completion_function) Completion function */ +/* _ux_utility_semaphore_put Signal transfer complete */ +/* */ +/* CALLED BY */ +/* */ +/* OHCI Controller Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_hcd_ohci_transfer_request_process(UX_TRANSFER *transfer_request) +{ + + /* Check if there is a function for the transfer completion. */ + if (transfer_request -> ux_transfer_request_completion_function != UX_NULL) + + /* Yes, so we call it! */ + transfer_request -> ux_transfer_request_completion_function(transfer_request); + else + + /* There is a semaphore so send the signal to the class. */ + _ux_utility_semaphore_put(&transfer_request -> ux_transfer_request_semaphore); + + /* Return to caller. */ + return; +} diff --git a/common/usbx_network/CMakeLists.txt b/common/usbx_network/CMakeLists.txt new file mode 100644 index 0000000..94b0a92 --- /dev/null +++ b/common/usbx_network/CMakeLists.txt @@ -0,0 +1,10 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/ux_network_driver.c + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/common/usbx_network/inc/ux_network_driver.h b/common/usbx_network/inc/ux_network_driver.h new file mode 100644 index 0000000..1e35c1d --- /dev/null +++ b/common/usbx_network/inc/ux_network_driver.h @@ -0,0 +1,111 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** USBX Network Driver for NETX 5.3 and above */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* ux_network_driver.h PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains all the header and extern functions used by the */ +/* USBX Network driver. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_NETWORK_DRIVER_H +#define UX_NETWORK_DRIVER_H + +#include "tx_api.h" +#include "nx_api.h" +#define USB_NETWORK_DEVICE_MAX_INSTANCES 8 +#define USB_NETWORK_DRIVER_SUCCESS UX_SUCCESS +#define USB_NETWORK_DRIVER_FAILURE UX_ERROR + +#define USB_NETWORK_DEVICE_MAC_HEADER_SIZE 14 +#define NX_ETHERNET_SIZE 14 +#define NX_ETHERNET_ARP 0x0806 +#define NX_ETHERNET_RARP 0x0835 +#define NX_ETHERNET_IP 0x0800 +#define NX_ETHERNET_IPV6 0x08DD +#define NX_ETHERNET_MTU 1514 + +typedef struct USB_NETWORK_DEVICE_STRUCT +{ + + /* ip_instance is populated by NetX, as part of the interface attachment. */ + NX_IP *ux_network_device_ip_instance; + + /* interface_ptr is populated by NetX, as part of the interface attachment. */ + NX_INTERFACE *ux_network_device_interface_ptr; + + /* Define synchronization objecs for deactivation. Note that these are only + used if the activation/deactivation functions are not called under interrupt. */ + UCHAR ux_network_device_activated_by_thread; + TX_MUTEX ux_network_device_deactivate_mutex; + TX_SEMAPHORE ux_network_device_deactivate_semaphore; + UCHAR ux_network_device_deactivate_thread_waiting; + UINT ux_network_device_num_threads_inside; + + /* usb_instance is populated by USB instance activation. */ + VOID *ux_network_device_usb_instance_ptr; + + /* The write_function is populated by USB instance activation. */ + UINT (*ux_network_device_write_function)(VOID *ux_instance, NX_PACKET *packet_ptr); + + USHORT ux_network_device_usb_link_up; + USHORT ux_network_device_link_status; + + ULONG ux_network_physical_address_msw; + ULONG ux_network_physical_address_lsw; + + +} USB_NETWORK_DEVICE_TYPE; + + +UINT _ux_network_driver_init(VOID); + +UINT _ux_network_driver_activate(VOID *ux_instance, UINT(*ux_network_device_write_function)(VOID *, NX_PACKET *), + VOID **ux_network_handle, ULONG physical_address_msw, ULONG physical_address_lsw); + +UINT _ux_network_driver_deactivate(VOID *ux_instance, VOID *ux_network_handle); + + +VOID _ux_network_driver_entry(NX_IP_DRIVER *nx_ip_driver); + +VOID _ux_network_driver_link_up(VOID *ux_network_handle); +VOID _ux_network_driver_link_down(VOID *ux_network_handle); + +VOID _ux_network_driver_packet_received(VOID *ux_network_handle, NX_PACKET *packet_ptr); +#endif diff --git a/common/usbx_network/src/ux_network_driver.c b/common/usbx_network/src/ux_network_driver.c new file mode 100644 index 0000000..ae22d83 --- /dev/null +++ b/common/usbx_network/src/ux_network_driver.c @@ -0,0 +1,937 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** USBX Network Driver for NETX 5.3 and above. */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#include "tx_api.h" +#include "tx_thread.h" +#include "nx_api.h" +#include "ux_api.h" + +#include "ux_network_driver.h" + +static UINT usb_network_driver_initialized; + +static USB_NETWORK_DEVICE_TYPE usb_network_devices[USB_NETWORK_DEVICE_MAX_INSTANCES]; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_network_init PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by the application to initialize the */ +/* USBX portion of the network driver. */ +/* */ +/* INPUT */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_network_driver_init(VOID) +{ + +UINT status = NX_SUCCESS; + + /* Check if driver is already initialized. */ + if (usb_network_driver_initialized == 0) + { + + /* Driver is not initialized yet. */ + usb_network_driver_initialized = 1; + + /* Reset the network device memory array. */ + _ux_utility_memory_set(&usb_network_devices[0], 0, sizeof(usb_network_devices)); + } + + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_network_driver_activate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* The USB network driver activate function is called as the USB instance */ +/* is created. This API takes a pointer to the instance, and returns a */ +/* ux_network_handle back to the instance. Everytime the instance receives*/ +/* a network packet, it should call ux_network_driver_packet_received with*/ +/* ux_network_handle. */ +/* */ +/* INPUT */ +/* */ +/* ux_instance Instance of the USBX network class */ +/* ux_network_device_write_function Address of the function to write a */ +/* packet when sent by the application */ +/* ux_network_handle Address where to store the network */ +/* handle */ +/* */ +/* physical_address_msw Most significant word of network ad */ +/* */ +/* physical_address_lsw Least significant word of network ad */ +/* */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Result */ +/* */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +UINT _ux_network_driver_activate(VOID *ux_instance, UINT(*ux_network_device_write_function)(VOID *, NX_PACKET *), + VOID **ux_network_handle, ULONG physical_address_msw, ULONG physical_address_lsw) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT i; + + /* Critical section. */ + TX_DISABLE + + /* Find an available entry in the usb_network_devices table. */ + for (i = 0; i < USB_NETWORK_DEVICE_MAX_INSTANCES; i++) + { + + /* If the ptr to instance is NULL, we have a free entry. */ + if (usb_network_devices[i].ux_network_device_usb_instance_ptr == NX_NULL) + { + + /* Add the instance of the USBX class driver to the network device. */ + usb_network_devices[i].ux_network_device_usb_instance_ptr = ux_instance; + + break; + } + } + + /* Unprotect the critical section. */ + TX_RESTORE + + /* Did we reach the max number of instance ? */ + if (i == USB_NETWORK_DEVICE_MAX_INSTANCES) + { + + /* Report error to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_MEMORY_INSUFFICIENT); + + /* Return error. */ + return(USB_NETWORK_DRIVER_FAILURE); + } + + /* Store the write function. */ + usb_network_devices[i].ux_network_device_write_function = ux_network_device_write_function; + + /* Store the physical address of the network interface. */ + usb_network_devices[i].ux_network_physical_address_msw = physical_address_msw; + usb_network_devices[i].ux_network_physical_address_lsw = physical_address_lsw; + + /* Are we not under interrupt? */ + if (TX_THREAD_GET_SYSTEM_STATE() == 0) + { + + /* Note that we were activated by a thread. */ + usb_network_devices[i].ux_network_device_activated_by_thread = UX_TRUE; + + /* Create deactivation sync objects. */ + _ux_utility_mutex_create(&usb_network_devices[i].ux_network_device_deactivate_mutex, "usb network device mutex"); + _ux_utility_semaphore_create(&usb_network_devices[i].ux_network_device_deactivate_semaphore, "usb network device semaphore", 0); + } + + /* Is there an interface at the NETX level ? */ + if (usb_network_devices[i].ux_network_device_interface_ptr) + { + + /* Store the physical address at the NETX level. */ + usb_network_devices[i].ux_network_device_interface_ptr -> nx_interface_physical_address_msw = physical_address_msw; + usb_network_devices[i].ux_network_device_interface_ptr -> nx_interface_physical_address_lsw = physical_address_lsw; + + /* Is the link UP ? */ + if (usb_network_devices[i].ux_network_device_interface_ptr -> nx_interface_link_up == NX_TRUE) + + /* Yes, store its state. */ + usb_network_devices[i].ux_network_device_link_status = NX_TRUE; + + } + else + + /* Link not yet up. */ + usb_network_devices[i].ux_network_device_link_status = NX_FALSE; + + + /* Is there a network handle associated ? */ + if (ux_network_handle) + + /* Yes, the application wants to know its address. */ + *ux_network_handle = (VOID*)&usb_network_devices[i]; + + /* The operation was successful. */ + return(USB_NETWORK_DRIVER_SUCCESS); +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_network_driver_deactivate PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* The USB network driver activate function is called as the USB instance */ +/* is created. This API takes a pointer to the instance, and returns a */ +/* ux_network_handle back to the instance. Everytime the instance receives*/ +/* a network packet, it should call ux_network_driver_packet_received with*/ +/* ux_network_handle. */ +/* */ +/* INPUT */ +/* */ +/* ux_instance Instance of the USBX network class */ +/* ux_network_device_write_function Address of the function to write a */ +/* packet when sent by the application */ +/* ux_network_handle Address where to store the network */ +/* handle */ +/* */ +/* physical_address_msw Most significant word of network ad */ +/* */ +/* physical_address_lsw Least significant word of network ad */ +/* */ +/* */ +/* */ +/* OUTPUT */ +/* */ +/* Result */ +/* */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +UINT _ux_network_driver_deactivate(VOID *ux_instance, VOID *ux_network_handle) +{ + +TX_INTERRUPT_SAVE_AREA + +USB_NETWORK_DEVICE_TYPE *usb_network_device; + + UX_PARAMETER_NOT_USED(ux_instance); + + /* Check if the handle exists. */ + if(ux_network_handle == NX_NULL) + return(USB_NETWORK_DRIVER_FAILURE); + + /* Cast the network handle properly. */ + usb_network_device = (USB_NETWORK_DEVICE_TYPE*) ux_network_handle; + + /* Critical section. */ + TX_DISABLE + + /* The link is down. */ + _ux_network_driver_link_down(ux_network_handle); + + /* Unprotect the critical section. */ + TX_RESTORE + + /* Are the sync objects valid? */ + if (usb_network_device -> ux_network_device_activated_by_thread) + { + + /* Get mutex. */ + _ux_utility_mutex_on(&usb_network_device -> ux_network_device_deactivate_mutex); + + /* Any threads in instance? */ + if (usb_network_device -> ux_network_device_num_threads_inside != 0) + { + + /* Signal that we're waiting. */ + usb_network_device -> ux_network_device_deactivate_thread_waiting = UX_TRUE; + + /* Release mutex. */ + _ux_utility_mutex_off(&usb_network_device -> ux_network_device_deactivate_mutex); + + /* Wait for last thread inside to resume us. */ + _ux_utility_semaphore_get(&usb_network_device -> ux_network_device_deactivate_semaphore, UX_WAIT_FOREVER); + + /* We're done waiting. */ + usb_network_device -> ux_network_device_deactivate_thread_waiting = UX_FALSE; + } + else + { + + /* Release mutex. */ + _ux_utility_mutex_off(&usb_network_device -> ux_network_device_deactivate_mutex); + } + + /* Delete sync objects. */ + _ux_utility_mutex_delete(&usb_network_device -> ux_network_device_deactivate_mutex); + _ux_utility_semaphore_delete(&usb_network_device -> ux_network_device_deactivate_semaphore); + + /* Reset for next activation. */ + usb_network_device -> ux_network_device_activated_by_thread = UX_FALSE; + } + + /* All threads are outside of the instance, and can't re-enter because the + link flag has been set to down. Now we can clean up. */ + + /* Reset the instance pointer. */ + usb_network_device -> ux_network_device_usb_instance_ptr = NX_NULL; + + /* And the write function ptr. */ + usb_network_device -> ux_network_device_write_function = NX_NULL; + + /* The operation was successful. */ + return(USB_NETWORK_DRIVER_SUCCESS); + +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_network_driver_entry PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by NETX. This is the dispatcher to all the */ +/* NETX function to the driver layer. */ +/* */ +/* INPUT */ +/* */ +/* nx_ip_driver Pointer to the NX_IP driver instance */ +/* */ +/* OUTPUT */ +/* */ +/* Result */ +/* */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* NETX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +VOID _ux_network_driver_entry(NX_IP_DRIVER *nx_ip_driver) +{ + +TX_INTERRUPT_SAVE_AREA +NX_IP *nx_ip; +NX_PACKET *packet_ptr; +ULONG *ethernet_frame_ptr; +NX_INTERFACE *nx_interface_ptr; +USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr; +UINT i; + + /* Get the pointer to the NX_IP instance. */ + nx_ip = nx_ip_driver -> nx_ip_driver_ptr; + + /* Set the default status return. */ + nx_ip_driver -> nx_ip_driver_status = NX_NOT_SUCCESSFUL; + + /* Get the pointer to the interface in local variable. */ + nx_interface_ptr = nx_ip_driver -> nx_ip_driver_interface; + + /* Is this the ATTACH command? */ + if (nx_ip_driver -> nx_ip_driver_command == NX_LINK_INTERFACE_ATTACH) + { + + /* Critical section. */ + TX_DISABLE + + /* Find an available entry in the usb_network_devices table. */ + for (i = 0; i < USB_NETWORK_DEVICE_MAX_INSTANCES; i++) + { + + /* If the interface pointer is NULL, it is free. */ + if (usb_network_devices[i].ux_network_device_interface_ptr == NX_NULL) + break; + + } + + /* Check if we have ran out of instances. */ + if (i == USB_NETWORK_DEVICE_MAX_INSTANCES) + + /* No more instances, set the error code. */ + nx_ip_driver -> nx_ip_driver_status = NX_NO_MORE_ENTRIES; + + else + { + + /* Save the IP address in the network instance. */ + usb_network_devices[i].ux_network_device_ip_instance = nx_ip; + + /* Save pointer to interface. */ + usb_network_devices[i].ux_network_device_interface_ptr = nx_interface_ptr; + + /* Set the USB class instance in the additional link. This will be used by the USB class driver. */ + nx_interface_ptr -> nx_interface_additional_link_info = (VOID *) &usb_network_devices[i]; + + /* The operation was successful. */ + nx_ip_driver -> nx_ip_driver_status = NX_SUCCESS; + } + + /* Unprotect the critical section. */ + TX_RESTORE + } + else + { + + /* Get the usb instance. */ + usb_network_device_ptr = (USB_NETWORK_DEVICE_TYPE *) nx_interface_ptr -> nx_interface_additional_link_info; + + /* Identify command. */ + switch(nx_ip_driver -> nx_ip_driver_command) + { + + case NX_LINK_INITIALIZE: + + /* INIT command, set the interface parameters. */ + nx_interface_ptr -> nx_interface_valid = NX_TRUE; + nx_interface_ptr -> nx_interface_address_mapping_needed = NX_TRUE; + nx_interface_ptr -> nx_interface_ip_mtu_size = NX_ETHERNET_MTU - NX_ETHERNET_SIZE; + + /* Set the link to down for now. */ + nx_interface_ptr -> nx_interface_link_up = NX_FALSE; + + /* Check if instance exists. */ + if (usb_network_device_ptr -> ux_network_device_usb_instance_ptr) + { + + /* Store the physical address in the nx interface. */ + nx_interface_ptr -> nx_interface_physical_address_msw = usb_network_device_ptr -> ux_network_physical_address_msw; + nx_interface_ptr -> nx_interface_physical_address_lsw = usb_network_device_ptr -> ux_network_physical_address_lsw; + + } + else + { + + /* Reset the physical address. */ + nx_interface_ptr -> nx_interface_physical_address_msw = 0; + nx_interface_ptr -> nx_interface_physical_address_lsw = 0; + } + + /* Operation is successful. */ + nx_ip_driver -> nx_ip_driver_status = NX_SUCCESS; + break; + + + + + case NX_LINK_ENABLE: + + /* Set the link state to UP. */ + nx_interface_ptr -> nx_interface_link_up = NX_TRUE; + + /* Reflect link state in network device. */ + if (usb_network_device_ptr -> ux_network_device_usb_link_up == NX_TRUE) + usb_network_device_ptr -> ux_network_device_link_status = NX_TRUE; + else + usb_network_device_ptr -> ux_network_device_link_status = NX_FALSE; + + nx_ip_driver -> nx_ip_driver_status = NX_SUCCESS; + break; + + + case NX_LINK_DISABLE: + + /* Set the link down. */ + nx_interface_ptr -> nx_interface_link_up = NX_FALSE; + usb_network_device_ptr -> ux_network_device_link_status = NX_FALSE; + nx_ip_driver -> nx_ip_driver_status = NX_SUCCESS; + break; + + + case NX_LINK_PACKET_SEND: + case NX_LINK_PACKET_BROADCAST: + case NX_LINK_ARP_SEND: + case NX_LINK_ARP_RESPONSE_SEND: + case NX_LINK_RARP_SEND: + + /* Place the ethernet frame at the front of the packet. */ + packet_ptr = nx_ip_driver -> nx_ip_driver_packet; + + /* Are the sync objects valid? */ + if (usb_network_device_ptr -> ux_network_device_activated_by_thread == UX_TRUE) + + /* Get mutex for checking link state and setting our state. */ + _ux_utility_mutex_on(&usb_network_device_ptr -> ux_network_device_deactivate_mutex); + + /* Do not send a packet if the link is not enabled. */ + if (usb_network_device_ptr -> ux_network_device_link_status == NX_TRUE) + { + + /* Increment number of threads inside this instance. */ + usb_network_device_ptr -> ux_network_device_num_threads_inside++; + + /* Are the sync objects valid? */ + if (usb_network_device_ptr -> ux_network_device_activated_by_thread == UX_TRUE) + + /* Release mutex. */ + _ux_utility_mutex_off(&usb_network_device_ptr -> ux_network_device_deactivate_mutex); + + /* Adjust the prepend pointer. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - NX_ETHERNET_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + NX_ETHERNET_SIZE; + + /* Setup the ethernet frame pointer to build the ethernet frame. Back up another 2 bytes to get 32-bit word alignment. */ + ethernet_frame_ptr = (ULONG*)(packet_ptr -> nx_packet_prepend_ptr - 2); + + /* Build the ethernet frame. */ + *ethernet_frame_ptr = nx_ip_driver -> nx_ip_driver_physical_address_msw; + *(ethernet_frame_ptr + 1) = nx_ip_driver -> nx_ip_driver_physical_address_lsw; + *(ethernet_frame_ptr + 2) = (nx_interface_ptr -> nx_interface_physical_address_msw << 16) | + (nx_interface_ptr -> nx_interface_physical_address_lsw >> 16); + *(ethernet_frame_ptr + 3) = (nx_interface_ptr -> nx_interface_physical_address_lsw << 16); + + if ((nx_ip_driver -> nx_ip_driver_command == NX_LINK_ARP_SEND)|| + (nx_ip_driver -> nx_ip_driver_command == NX_LINK_ARP_RESPONSE_SEND)) + { + *(ethernet_frame_ptr+3) |= NX_ETHERNET_ARP; + } + else if (nx_ip_driver -> nx_ip_driver_command == NX_LINK_RARP_SEND) + { + *(ethernet_frame_ptr+3) |= NX_ETHERNET_RARP; + } + else + { +#ifdef FEATURE_NX_IPV6 + if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V4) +#endif /* FEATURE_NX_IPV6 */ + *(ethernet_frame_ptr+3) |= NX_ETHERNET_IP; +#ifdef FEATURE_NX_IPV6 + else if (packet_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6) + *(ethernet_frame_ptr+3) |= NX_ETHERNET_IPV6; + else + { + /* Unknown IP version */ + /* free the packet that we will not send */ + nx_packet_release(packet_ptr); + nx_ip_driver -> nx_ip_driver_status = NX_NOT_SUCCESSFUL; + break; + } +#endif /* FEATURE_NX_IPV6 */ + } + + /* Endian swapping if NX_LITTLE_ENDIAN is defined. */ + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr+1)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr+2)); + NX_CHANGE_ULONG_ENDIAN(*(ethernet_frame_ptr+3)); + + /* Write the packet or queue it. */ + nx_ip_driver -> nx_ip_driver_status = + usb_network_device_ptr -> ux_network_device_write_function(usb_network_device_ptr -> ux_network_device_usb_instance_ptr, + packet_ptr); + + /* Are the sync objects valid? */ + if (usb_network_device_ptr -> ux_network_device_activated_by_thread == UX_TRUE) + { + + /* Get mutex. */ + _ux_utility_mutex_on(&usb_network_device_ptr -> ux_network_device_deactivate_mutex); + + /* Decrement number of threads in instance. */ + usb_network_device_ptr -> ux_network_device_num_threads_inside--; + + /* No more threads in the instance? */ + if (usb_network_device_ptr -> ux_network_device_num_threads_inside == 0) + { + + /* Release mutex. */ + _ux_utility_mutex_off(&usb_network_device_ptr -> ux_network_device_deactivate_mutex); + + /* Anyone waiting for us to exit? */ + if (usb_network_device_ptr -> ux_network_device_deactivate_thread_waiting == UX_TRUE) + + /* Resume deactivate thread waiting. */ + _ux_utility_semaphore_put(&usb_network_device_ptr -> ux_network_device_deactivate_semaphore); + } + else + { + + /* Release mutex. */ + _ux_utility_mutex_off(&usb_network_device_ptr -> ux_network_device_deactivate_mutex); + } + } + } + else + { + + /* Are the sync objects valid? */ + if (usb_network_device_ptr -> ux_network_device_activated_by_thread == UX_TRUE) + + /* Release mutex. */ + _ux_utility_mutex_off(&usb_network_device_ptr -> ux_network_device_deactivate_mutex); + + /* Link down, throw away packet. */ + nx_packet_transmit_release(packet_ptr); + nx_ip_driver -> nx_ip_driver_status = NX_SUCCESS; + + /* Report error to application. */ + _ux_system_error_handler(UX_SYSTEM_LEVEL_THREAD, UX_SYSTEM_CONTEXT_CLASS, UX_CLASS_CDC_ECM_LINK_STATE_DOWN_ERROR); + } + + break; + + case NX_LINK_UNINITIALIZE: + + usb_network_driver_initialized = 0; + + break; + + case NX_LINK_MULTICAST_JOIN: + case NX_LINK_MULTICAST_LEAVE: + case NX_LINK_GET_STATUS: + case NX_LINK_GET_ERROR_COUNT: + case NX_LINK_GET_RX_COUNT: + case NX_LINK_GET_TX_COUNT: + case NX_LINK_GET_ALLOC_ERRORS: + case NX_LINK_GET_SPEED: + case NX_LINK_GET_DUPLEX_TYPE: + case NX_LINK_USER_COMMAND : + default: + + /* Invalid driver request. */ + nx_ip_driver -> nx_ip_driver_status = NX_UNHANDLED_COMMAND; + + /* Return the link status in the supplied return pointer. */ + if(nx_ip_driver -> nx_ip_driver_return_ptr) + *(nx_ip_driver -> nx_ip_driver_return_ptr) = (ULONG)0; + break; + } + } + + /* We are done here. */ + return; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_network_driver_packet_received PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by USBX when a packet has been receiver over */ +/* the USB. */ +/* */ +/* INPUT */ +/* */ +/* ux_network_handle Handle of the USB network instance */ +/* packet_ptr Pointer to packet received */ +/* */ +/* OUTPUT */ +/* */ +/* Result */ +/* */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +VOID _ux_network_driver_packet_received(VOID *ux_network_handle, NX_PACKET *packet_ptr) +{ + +USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr = (USB_NETWORK_DEVICE_TYPE*) ux_network_handle; + +ULONG packet_type; +NX_IP *nx_ip; + + /* Check the state of the Link. */ + if (usb_network_device_ptr -> ux_network_device_link_status != NX_TRUE) + { + + /* Link down, throw away packet. */ + nx_packet_release(packet_ptr); + return; + + } + + /* Pickup the packet header to determine where the packet needs to be + sent. */ + packet_type = _ux_utility_short_get_big_endian(packet_ptr -> nx_packet_prepend_ptr + 12); + + /* Storing in into the packet the interface. */ + packet_ptr -> nx_packet_ip_interface = usb_network_device_ptr -> ux_network_device_interface_ptr; + + /* Get the IP instance. */ + nx_ip = usb_network_device_ptr -> ux_network_device_ip_instance; + + /* Route the incoming packet according to its ethernet type. */ + switch (packet_type) + { + case NX_ETHERNET_IP : + + /* Note: The length reported by some Ethernet hardware includes + bytes after the packet as well as the Ethernet header. In some + cases, the actual packet length after the Ethernet header should + be derived from the length in the IP header (lower 16 bits of + the first 32-bit word). */ + + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE; + + /* Route to the ip receive function. */ + _nx_ip_packet_deferred_receive(nx_ip, packet_ptr); + + break; + + case NX_ETHERNET_ARP : + + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE; + + /* Route to the ARP receive function. */ + _nx_arp_packet_deferred_receive(nx_ip, packet_ptr); + + break; + + case NX_ETHERNET_RARP : + + /* Clean off the Ethernet header. */ + packet_ptr -> nx_packet_prepend_ptr = + packet_ptr -> nx_packet_prepend_ptr + NX_ETHERNET_SIZE; + + /* Adjust the packet length. */ + packet_ptr -> nx_packet_length = + packet_ptr -> nx_packet_length - NX_ETHERNET_SIZE; + + /* Route to the RARP receive function. */ + _nx_rarp_packet_deferred_receive(nx_ip, packet_ptr); + + break; + + + default : + + /* Invalid ethernet header... release the packet. */ + nx_packet_release(packet_ptr); + + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_network_driver_link_up PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by USBX when the line link is up */ +/* */ +/* INPUT */ +/* */ +/* ux_network_handle Handle of the USB network instance */ +/* */ +/* OUTPUT */ +/* */ +/* Result */ +/* */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +VOID _ux_network_driver_link_up(VOID *ux_network_handle) +{ + +USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr = (USB_NETWORK_DEVICE_TYPE*)ux_network_handle; + + /* The USB side of the link is UP. */ + usb_network_device_ptr -> ux_network_device_usb_link_up = NX_TRUE; + + /* Check if there is an existing interface. */ + if (usb_network_device_ptr -> ux_network_device_interface_ptr) + { + + /* Set link status. */ + if (usb_network_device_ptr -> ux_network_device_interface_ptr -> nx_interface_link_up) + usb_network_device_ptr -> ux_network_device_link_status = NX_TRUE; + else + usb_network_device_ptr -> ux_network_device_link_status = NX_FALSE; + } + +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _ux_network_driver_link_down PORTABLE C */ +/* 6.0 */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is called by USBX when the link is down. */ +/* */ +/* INPUT */ +/* */ +/* ux_network_handle Handle of the USB network instance */ +/* */ +/* OUTPUT */ +/* */ +/* Result */ +/* */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* USBX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ +VOID _ux_network_driver_link_down(VOID *ux_network_handle) +{ + +USB_NETWORK_DEVICE_TYPE *usb_network_device_ptr = (USB_NETWORK_DEVICE_TYPE*)ux_network_handle; + + /* Set the USB link status. */ + usb_network_device_ptr -> ux_network_device_usb_link_up = NX_FALSE; + + /* Set the link status. */ + usb_network_device_ptr -> ux_network_device_link_status = NX_FALSE; + +} diff --git a/docs/USBX_Device_Stack_User_Guide.docx b/docs/USBX_Device_Stack_User_Guide.docx new file mode 100644 index 0000000..6d9f66a Binary files /dev/null and b/docs/USBX_Device_Stack_User_Guide.docx differ diff --git a/docs/USBX_Device_Stack_User_Guide_Supplemental.pdf b/docs/USBX_Device_Stack_User_Guide_Supplemental.pdf new file mode 100644 index 0000000..5e1318b Binary files /dev/null and b/docs/USBX_Device_Stack_User_Guide_Supplemental.pdf differ diff --git a/docs/USBX_Express_Startup.pdf b/docs/USBX_Express_Startup.pdf new file mode 100755 index 0000000..7d26127 Binary files /dev/null and b/docs/USBX_Express_Startup.pdf differ diff --git a/docs/USBX_Host_Stack_UVC_User_Guide.docx b/docs/USBX_Host_Stack_UVC_User_Guide.docx new file mode 100644 index 0000000..d942d89 Binary files /dev/null and b/docs/USBX_Host_Stack_UVC_User_Guide.docx differ diff --git a/docs/USBX_Host_Stack_User_Guide.docx b/docs/USBX_Host_Stack_User_Guide.docx new file mode 100644 index 0000000..8374609 Binary files /dev/null and b/docs/USBX_Host_Stack_User_Guide.docx differ diff --git a/docs/USBX_Host_Stack_User_Guide_Supplemental.pdf b/docs/USBX_Host_Stack_User_Guide_Supplemental.pdf new file mode 100644 index 0000000..b5632aa Binary files /dev/null and b/docs/USBX_Host_Stack_User_Guide_Supplemental.pdf differ diff --git a/ports/cortex_m0/gnu/CMakeLists.txt b/ports/cortex_m0/gnu/CMakeLists.txt new file mode 100644 index 0000000..75c7953 --- /dev/null +++ b/ports/cortex_m0/gnu/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m0/gnu/inc/ux_port.h b/ports/cortex_m0/gnu/inc/ux_port.h new file mode 100644 index 0000000..ca1b561 --- /dev/null +++ b/ports/cortex_m0/gnu/inc/ux_port.h @@ -0,0 +1,215 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* ux_port.h Cortex-M0/GNU */ +/* 6.0 */ +/* */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make USBX function */ +/* identically on a variety of different processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_PORT_H +#define UX_PORT_H + + +/* Determine if the optional USBX user define file should be used. */ + +#ifdef UX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in ux_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "ux_user.h" +#endif + + +/* Include library header files. */ + +#include +#include + + +/* CPU definition for X86 systems without preemptive timer function. + This will make USBX uses the controller for the timer. */ + +#undef THREADX_X86_NO_PTIMER + + +/* For X86 systems, the define #define UX_USE_IO_INSTRUCTIONS should be used. */ + + +/* Define additional generic USBX types. */ + +typedef long SLONG; + + +/* Generic USBX Project constants follow. */ + +#ifndef UX_PERIODIC_RATE +#define UX_PERIODIC_RATE 100 +#endif + +#ifndef UX_MAX_CLASS_DRIVER +#define UX_MAX_CLASS_DRIVER 1 +#endif + +#ifndef UX_MAX_SLAVE_CLASS_DRIVER +#define UX_MAX_SLAVE_CLASS_DRIVER 1 +#endif + +#ifndef UX_MAX_HCD +#define UX_MAX_HCD 1 +#endif + +#ifndef UX_MAX_DEVICES +#define UX_MAX_DEVICES 1 +#endif + +#ifndef UX_MAX_ED +#define UX_MAX_ED 70 +#endif + +#ifndef UX_MAX_TD +#define UX_MAX_TD 16 +#endif + +#ifndef UX_MAX_ISO_TD +#define UX_MAX_ISO_TD 0 +#endif + +#ifndef UX_HOST_ENUM_THREAD_STACK_SIZE +#define UX_HOST_ENUM_THREAD_STACK_SIZE (1*1024) +#endif + +#ifndef UX_THREAD_STACK_SIZE +#define UX_THREAD_STACK_SIZE (1*1024) +#endif + +#ifndef UX_THREAD_PRIORITY_ENUM +#define UX_THREAD_PRIORITY_ENUM 20 +#endif + +#ifndef UX_THREAD_PRIORITY_CLASS +#define UX_THREAD_PRIORITY_CLASS 20 +#endif + +#ifndef UX_THREAD_PRIORITY_KEYBOARD +#define UX_THREAD_PRIORITY_KEYBOARD 20 +#endif + +#ifndef UX_THREAD_PRIORITY_HCD +#define UX_THREAD_PRIORITY_HCD 2 +#endif + +#ifndef UX_THREAD_PRIORITY_DCD +#define UX_THREAD_PRIORITY_DCD 2 +#endif + +#ifndef UX_NO_TIME_SLICE +#define UX_NO_TIME_SLICE 0 +#endif + +#ifndef UX_MAX_SLAVE_LUN +#define UX_MAX_SLAVE_LUN 1 +#endif + +#ifndef UX_MAX_HOST_LUN +#define UX_MAX_HOST_LUN 1 +#endif + +#ifndef UX_HOST_CLASS_STORAGE_MAX_MEDIA +#define UX_HOST_CLASS_STORAGE_MAX_MEDIA 1 +#endif + +#ifndef UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH +#define UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH 256 +#endif + + +#ifndef UX_SLAVE_REQUEST_DATA_MAX_LENGTH +#define UX_SLAVE_REQUEST_DATA_MAX_LENGTH 2048 +#endif + +#ifndef UX_USE_IO_INSTRUCTIONS + +/* Don't use IO instructions if this define is not set. Default to memory mapped. */ + +#define inpb(a) *((UCHAR *) (a)) +#define inpw(a) *((USHORT *) (a)) +#define inpl(a) *((ULONG *) (a)) +#define outpb(a, b) *((UCHAR *) (a)) = ((UCHAR) (b)) +#define outpw(a, b) *((USHORT *) (a)) = ((USHORT) (b)) +#define outpl(a, b) *((ULONG *) (a)) = ((ULONG) (b)) +#else + + +/* Define simple prototypes for non-memory mapped hardware access. */ + +UCHAR inpb(ULONG); +USHORT inpw(ULONG); +ULONG inpl(ULONG); + +VOID outpb(ULONG,UCHAR); +VOID outpw(ULONG,USHORT); +VOID outpl(ULONG,ULONG); + +#endif + + +/* Define interrupt lockout constructs to protect the memory allocation/release which could happen + under ISR in the device stack. */ + +#define UX_INT_SAVE_AREA unsigned int old_interrupt_posture; +#define UX_DISABLE_INTS old_interrupt_posture = tx_interrupt_control(TX_INT_DISABLE); +#define UX_RESTORE_INTS tx_interrupt_control(old_interrupt_posture); + + +/* Define the version ID of USBX. This may be utilized by the application. */ + +#ifdef UX_SYSTEM_INIT +CHAR _ux_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M0/GNU Version 6.0 *"; +#else +extern CHAR _ux_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m3/gnu/CMakeLists.txt b/ports/cortex_m3/gnu/CMakeLists.txt new file mode 100644 index 0000000..75c7953 --- /dev/null +++ b/ports/cortex_m3/gnu/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m3/gnu/inc/ux_port.h b/ports/cortex_m3/gnu/inc/ux_port.h new file mode 100644 index 0000000..db505f8 --- /dev/null +++ b/ports/cortex_m3/gnu/inc/ux_port.h @@ -0,0 +1,215 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* ux_port.h Cortex-M3/GNU */ +/* 6.0 */ +/* */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make USBX function */ +/* identically on a variety of different processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_PORT_H +#define UX_PORT_H + + +/* Determine if the optional USBX user define file should be used. */ + +#ifdef UX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in ux_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "ux_user.h" +#endif + + +/* Include library header files. */ + +#include +#include + + +/* CPU definition for X86 systems without preemptive timer function. + This will make USBX uses the controller for the timer. */ + +#undef THREADX_X86_NO_PTIMER + + +/* For X86 systems, the define #define UX_USE_IO_INSTRUCTIONS should be used. */ + + +/* Define additional generic USBX types. */ + +typedef long SLONG; + + +/* Generic USBX Project constants follow. */ + +#ifndef UX_PERIODIC_RATE +#define UX_PERIODIC_RATE 100 +#endif + +#ifndef UX_MAX_CLASS_DRIVER +#define UX_MAX_CLASS_DRIVER 2 +#endif + +#ifndef UX_MAX_SLAVE_CLASS_DRIVER +#define UX_MAX_SLAVE_CLASS_DRIVER 2 +#endif + +#ifndef UX_MAX_HCD +#define UX_MAX_HCD 1 +#endif + +#ifndef UX_MAX_DEVICES +#define UX_MAX_DEVICES 2 +#endif + +#ifndef UX_MAX_ED +#define UX_MAX_ED 80 +#endif + +#ifndef UX_MAX_TD +#define UX_MAX_TD 32 +#endif + +#ifndef UX_MAX_ISO_TD +#define UX_MAX_ISO_TD 2 +#endif + +#ifndef UX_HOST_ENUM_THREAD_STACK_SIZE +#define UX_HOST_ENUM_THREAD_STACK_SIZE (2*1024) +#endif + +#ifndef UX_THREAD_STACK_SIZE +#define UX_THREAD_STACK_SIZE (1*1024) +#endif + +#ifndef UX_THREAD_PRIORITY_ENUM +#define UX_THREAD_PRIORITY_ENUM 20 +#endif + +#ifndef UX_THREAD_PRIORITY_CLASS +#define UX_THREAD_PRIORITY_CLASS 20 +#endif + +#ifndef UX_THREAD_PRIORITY_KEYBOARD +#define UX_THREAD_PRIORITY_KEYBOARD 20 +#endif + +#ifndef UX_THREAD_PRIORITY_HCD +#define UX_THREAD_PRIORITY_HCD 2 +#endif + +#ifndef UX_THREAD_PRIORITY_DCD +#define UX_THREAD_PRIORITY_DCD 2 +#endif + +#ifndef UX_NO_TIME_SLICE +#define UX_NO_TIME_SLICE 0 +#endif + +#ifndef UX_MAX_SLAVE_LUN +#define UX_MAX_SLAVE_LUN 1 +#endif + +#ifndef UX_MAX_HOST_LUN +#define UX_MAX_HOST_LUN 1 +#endif + +#ifndef UX_HOST_CLASS_STORAGE_MAX_MEDIA +#define UX_HOST_CLASS_STORAGE_MAX_MEDIA 1 +#endif + +#ifndef UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH +#define UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH 256 +#endif + + +#ifndef UX_SLAVE_REQUEST_DATA_MAX_LENGTH +#define UX_SLAVE_REQUEST_DATA_MAX_LENGTH 2048 +#endif + +#ifndef UX_USE_IO_INSTRUCTIONS + +/* Don't use IO instructions if this define is not set. Default to memory mapped. */ + +#define inpb(a) *((UCHAR *) (a)) +#define inpw(a) *((USHORT *) (a)) +#define inpl(a) *((ULONG *) (a)) +#define outpb(a, b) *((UCHAR *) (a)) = ((UCHAR) (b)) +#define outpw(a, b) *((USHORT *) (a)) = ((USHORT) (b)) +#define outpl(a, b) *((ULONG *) (a)) = ((ULONG) (b)) +#else + + +/* Define simple prototypes for non-memory mapped hardware access. */ + +UCHAR inpb(ULONG); +USHORT inpw(ULONG); +ULONG inpl(ULONG); + +VOID outpb(ULONG,UCHAR); +VOID outpw(ULONG,USHORT); +VOID outpl(ULONG,ULONG); + +#endif + + +/* Define interrupt lockout constructs to protect the memory allocation/release which could happen + under ISR in the device stack. */ + +#define UX_INT_SAVE_AREA unsigned int old_interrupt_posture; +#define UX_DISABLE_INTS old_interrupt_posture = tx_interrupt_control(TX_INT_DISABLE); +#define UX_RESTORE_INTS tx_interrupt_control(old_interrupt_posture); + + +/* Define the version ID of USBX. This may be utilized by the application. */ + +#ifdef UX_SYSTEM_INIT +CHAR _ux_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M3/GNU Version 6.0 *"; +#else +extern CHAR _ux_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m4/gnu/CMakeLists.txt b/ports/cortex_m4/gnu/CMakeLists.txt new file mode 100644 index 0000000..75c7953 --- /dev/null +++ b/ports/cortex_m4/gnu/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m4/gnu/inc/ux_port.h b/ports/cortex_m4/gnu/inc/ux_port.h new file mode 100644 index 0000000..b9a8656 --- /dev/null +++ b/ports/cortex_m4/gnu/inc/ux_port.h @@ -0,0 +1,215 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* ux_port.h Cortex-M4/GNU */ +/* 6.0 */ +/* */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make USBX function */ +/* identically on a variety of different processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_PORT_H +#define UX_PORT_H + + +/* Determine if the optional USBX user define file should be used. */ + +#ifdef UX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in ux_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "ux_user.h" +#endif + + +/* Include library header files. */ + +#include +#include + + +/* CPU definition for X86 systems without preemptive timer function. + This will make USBX uses the controller for the timer. */ + +#undef THREADX_X86_NO_PTIMER + + +/* For X86 systems, the define #define UX_USE_IO_INSTRUCTIONS should be used. */ + + +/* Define additional generic USBX types. */ + +typedef long SLONG; + + +/* Generic USBX Project constants follow. */ + +#ifndef UX_PERIODIC_RATE +#define UX_PERIODIC_RATE 100 +#endif + +#ifndef UX_MAX_CLASS_DRIVER +#define UX_MAX_CLASS_DRIVER 2 +#endif + +#ifndef UX_MAX_SLAVE_CLASS_DRIVER +#define UX_MAX_SLAVE_CLASS_DRIVER 2 +#endif + +#ifndef UX_MAX_HCD +#define UX_MAX_HCD 2 +#endif + +#ifndef UX_MAX_DEVICES +#define UX_MAX_DEVICES 8 +#endif + +#ifndef UX_MAX_ED +#define UX_MAX_ED 80 +#endif + +#ifndef UX_MAX_TD +#define UX_MAX_TD 32 +#endif + +#ifndef UX_MAX_ISO_TD +#define UX_MAX_ISO_TD 8 +#endif + +#ifndef UX_HOST_ENUM_THREAD_STACK_SIZE +#define UX_HOST_ENUM_THREAD_STACK_SIZE (2*1024) +#endif + +#ifndef UX_THREAD_STACK_SIZE +#define UX_THREAD_STACK_SIZE (1*1024) +#endif + +#ifndef UX_THREAD_PRIORITY_ENUM +#define UX_THREAD_PRIORITY_ENUM 20 +#endif + +#ifndef UX_THREAD_PRIORITY_CLASS +#define UX_THREAD_PRIORITY_CLASS 20 +#endif + +#ifndef UX_THREAD_PRIORITY_KEYBOARD +#define UX_THREAD_PRIORITY_KEYBOARD 20 +#endif + +#ifndef UX_THREAD_PRIORITY_HCD +#define UX_THREAD_PRIORITY_HCD 2 +#endif + +#ifndef UX_THREAD_PRIORITY_DCD +#define UX_THREAD_PRIORITY_DCD 2 +#endif + +#ifndef UX_NO_TIME_SLICE +#define UX_NO_TIME_SLICE 0 +#endif + +#ifndef UX_MAX_SLAVE_LUN +#define UX_MAX_SLAVE_LUN 2 +#endif + +#ifndef UX_MAX_HOST_LUN +#define UX_MAX_HOST_LUN 2 +#endif + +#ifndef UX_HOST_CLASS_STORAGE_MAX_MEDIA +#define UX_HOST_CLASS_STORAGE_MAX_MEDIA 2 +#endif + +#ifndef UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH +#define UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH 256 +#endif + + +#ifndef UX_SLAVE_REQUEST_DATA_MAX_LENGTH +#define UX_SLAVE_REQUEST_DATA_MAX_LENGTH 2048 +#endif + +#ifndef UX_USE_IO_INSTRUCTIONS + +/* Don't use IO instructions if this define is not set. Default to memory mapped. */ + +#define inpb(a) *((UCHAR *) (a)) +#define inpw(a) *((USHORT *) (a)) +#define inpl(a) *((ULONG *) (a)) +#define outpb(a, b) *((UCHAR *) (a)) = ((UCHAR) (b)) +#define outpw(a, b) *((USHORT *) (a)) = ((USHORT) (b)) +#define outpl(a, b) *((ULONG *) (a)) = ((ULONG) (b)) +#else + + +/* Define simple prototypes for non-memory mapped hardware access. */ + +UCHAR inpb(ULONG); +USHORT inpw(ULONG); +ULONG inpl(ULONG); + +VOID outpb(ULONG,UCHAR); +VOID outpw(ULONG,USHORT); +VOID outpl(ULONG,ULONG); + +#endif + + +/* Define interrupt lockout constructs to protect the memory allocation/release which could happen + under ISR in the device stack. */ + +#define UX_INT_SAVE_AREA unsigned int old_interrupt_posture; +#define UX_DISABLE_INTS old_interrupt_posture = tx_interrupt_control(TX_INT_DISABLE); +#define UX_RESTORE_INTS tx_interrupt_control(old_interrupt_posture); + + +/* Define the version ID of USBX. This may be utilized by the application. */ + +#ifdef UX_SYSTEM_INIT +CHAR _ux_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M4/GNU Version 6.0 *"; +#else +extern CHAR _ux_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m7/gnu/CMakeLists.txt b/ports/cortex_m7/gnu/CMakeLists.txt new file mode 100644 index 0000000..75c7953 --- /dev/null +++ b/ports/cortex_m7/gnu/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m7/gnu/inc/ux_port.h b/ports/cortex_m7/gnu/inc/ux_port.h new file mode 100644 index 0000000..3411fed --- /dev/null +++ b/ports/cortex_m7/gnu/inc/ux_port.h @@ -0,0 +1,215 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** USBX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* ux_port.h Cortex-M7/GNU */ +/* 6.0 */ +/* */ +/* AUTHOR */ +/* */ +/* Chaoqiong Xiao, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make USBX function */ +/* identically on a variety of different processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Chaoqiong Xiao Initial Version 6.0 */ +/* */ +/**************************************************************************/ + +#ifndef UX_PORT_H +#define UX_PORT_H + + +/* Determine if the optional USBX user define file should be used. */ + +#ifdef UX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in ux_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "ux_user.h" +#endif + + +/* Include library header files. */ + +#include +#include + + +/* CPU definition for X86 systems without preemptive timer function. + This will make USBX uses the controller for the timer. */ + +#undef THREADX_X86_NO_PTIMER + + +/* For X86 systems, the define #define UX_USE_IO_INSTRUCTIONS should be used. */ + + +/* Define additional generic USBX types. */ + +typedef long SLONG; + + +/* Generic USBX Project constants follow. */ + +#ifndef UX_PERIODIC_RATE +#define UX_PERIODIC_RATE 100 +#endif + +#ifndef UX_MAX_CLASS_DRIVER +#define UX_MAX_CLASS_DRIVER 8 +#endif + +#ifndef UX_MAX_SLAVE_CLASS_DRIVER +#define UX_MAX_SLAVE_CLASS_DRIVER 4 +#endif + +#ifndef UX_MAX_HCD +#define UX_MAX_HCD 2 +#endif + +#ifndef UX_MAX_DEVICES +#define UX_MAX_DEVICES 8 +#endif + +#ifndef UX_MAX_ED +#define UX_MAX_ED 80 +#endif + +#ifndef UX_MAX_TD +#define UX_MAX_TD 32 +#endif + +#ifndef UX_MAX_ISO_TD +#define UX_MAX_ISO_TD 16 +#endif + +#ifndef UX_HOST_ENUM_THREAD_STACK_SIZE +#define UX_HOST_ENUM_THREAD_STACK_SIZE (2*1024) +#endif + +#ifndef UX_THREAD_STACK_SIZE +#define UX_THREAD_STACK_SIZE (1*1024) +#endif + +#ifndef UX_THREAD_PRIORITY_ENUM +#define UX_THREAD_PRIORITY_ENUM 20 +#endif + +#ifndef UX_THREAD_PRIORITY_CLASS +#define UX_THREAD_PRIORITY_CLASS 20 +#endif + +#ifndef UX_THREAD_PRIORITY_KEYBOARD +#define UX_THREAD_PRIORITY_KEYBOARD 20 +#endif + +#ifndef UX_THREAD_PRIORITY_HCD +#define UX_THREAD_PRIORITY_HCD 2 +#endif + +#ifndef UX_THREAD_PRIORITY_DCD +#define UX_THREAD_PRIORITY_DCD 2 +#endif + +#ifndef UX_NO_TIME_SLICE +#define UX_NO_TIME_SLICE 0 +#endif + +#ifndef UX_MAX_SLAVE_LUN +#define UX_MAX_SLAVE_LUN 2 +#endif + +#ifndef UX_MAX_HOST_LUN +#define UX_MAX_HOST_LUN 2 +#endif + +#ifndef UX_HOST_CLASS_STORAGE_MAX_MEDIA +#define UX_HOST_CLASS_STORAGE_MAX_MEDIA 2 +#endif + +#ifndef UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH +#define UX_SLAVE_REQUEST_CONTROL_MAX_LENGTH 256 +#endif + + +#ifndef UX_SLAVE_REQUEST_DATA_MAX_LENGTH +#define UX_SLAVE_REQUEST_DATA_MAX_LENGTH 4096 +#endif + +#ifndef UX_USE_IO_INSTRUCTIONS + +/* Don't use IO instructions if this define is not set. Default to memory mapped. */ + +#define inpb(a) *((UCHAR *) (a)) +#define inpw(a) *((USHORT *) (a)) +#define inpl(a) *((ULONG *) (a)) +#define outpb(a, b) *((UCHAR *) (a)) = ((UCHAR) (b)) +#define outpw(a, b) *((USHORT *) (a)) = ((USHORT) (b)) +#define outpl(a, b) *((ULONG *) (a)) = ((ULONG) (b)) +#else + + +/* Define simple prototypes for non-memory mapped hardware access. */ + +UCHAR inpb(ULONG); +USHORT inpw(ULONG); +ULONG inpl(ULONG); + +VOID outpb(ULONG,UCHAR); +VOID outpw(ULONG,USHORT); +VOID outpl(ULONG,ULONG); + +#endif + + +/* Define interrupt lockout constructs to protect the memory allocation/release which could happen + under ISR in the device stack. */ + +#define UX_INT_SAVE_AREA unsigned int old_interrupt_posture; +#define UX_DISABLE_INTS old_interrupt_posture = tx_interrupt_control(TX_INT_DISABLE); +#define UX_RESTORE_INTS tx_interrupt_control(old_interrupt_posture); + + +/* Define the version ID of USBX. This may be utilized by the application. */ + +#ifdef UX_SYSTEM_INIT +CHAR _ux_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * USBX Cortex-M7/GNU Version 6.0 *"; +#else +extern CHAR _ux_version_id[]; +#endif + +#endif + diff --git a/rebuild.sh b/rebuild.sh new file mode 100755 index 0000000..539f3dd --- /dev/null +++ b/rebuild.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# Use paths relative to this script's location +SCRIPT=$(readlink -f "$0") +BASEDIR=$(dirname "$SCRIPT") + +# If you want to build into a different directory, change this variable +BUILDDIR="$BASEDIR/build" + +# Create our build folder if required and clear it +mkdir -p $BUILDDIR +rm -rf $BUILDDIR/* + +# Generate the build system using Ninja +cmake -B"$BUILDDIR" -GNinja -DCMAKE_TOOLCHAIN_FILE=$BASEDIR/cmake/arm-gcc-toolchain.cmake $BASEDIR +# Generate the build system using the system default +# cmake -B"$BUILDDIR" -DCMAKE_TOOLCHAIN_FILE=$BASEDIR/cmake/arm-gcc-toolchain.cmake $BASEDIR + +# And then do the build +cmake --build $BUILDDIR diff --git a/samples/demo_usbx.c b/samples/demo_usbx.c new file mode 100644 index 0000000..1d7de2b --- /dev/null +++ b/samples/demo_usbx.c @@ -0,0 +1,395 @@ +/* This is a small demo of the USBX */ + +#include "ux_api.h" +#include "ux_system.h" +#include "ux_utility.h" +#include "ux_host_class_dpump.h" +#include "ux_device_class_dpump.h" + + +/* Define USBX demo constants. */ + +#define UX_DEMO_STACK_SIZE 4096 +#define UX_DEMO_BUFFER_SIZE 2048 +#define UX_DEMO_RUN 1 +#define UX_DEMO_MEMORY_SIZE (64*1024) + + +/* Define the counters used in the demo application... */ + +ULONG thread_0_counter; +ULONG thread_1_counter; +ULONG error_counter; + + +/* Define USBX demo global variables. */ + +unsigned char host_out_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE]; +unsigned char host_in_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE]; +unsigned char slave_buffer[UX_HOST_CLASS_DPUMP_PACKET_SIZE]; + +UX_HOST_CLASS *class_driver; +UX_HOST_CLASS_DPUMP *dpump; +UX_SLAVE_CLASS_DPUMP *dpump_slave; + + +#define DEVICE_FRAMEWORK_LENGTH_FULL_SPEED 50 +UCHAR device_framework_full_speed[] = { + + /* Device descriptor */ + 0x12, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, 0x08, + 0xec, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, + + /* Configuration descriptor */ + 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0, + 0x32, + + /* Interface descriptor */ + 0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99, + 0x00, + + /* Endpoint descriptor (Bulk Out) */ + 0x07, 0x05, 0x01, 0x02, 0x40, 0x00, 0x00, + + /* Endpoint descriptor (Bulk In) */ + 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00 + }; + + +#define DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED 60 +UCHAR device_framework_high_speed[] = { + + /* Device descriptor */ + 0x12, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, + 0x0a, 0x07, 0x25, 0x40, 0x01, 0x00, 0x01, 0x02, + 0x03, 0x01, + + /* Device qualifier descriptor */ + 0x0a, 0x06, 0x00, 0x02, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x00, + + /* Configuration descriptor */ + 0x09, 0x02, 0x20, 0x00, 0x01, 0x01, 0x00, 0xc0, + 0x32, + + /* Interface descriptor */ + 0x09, 0x04, 0x00, 0x00, 0x02, 0x99, 0x99, 0x99, + 0x00, + + /* Endpoint descriptor (Bulk Out) */ + 0x07, 0x05, 0x01, 0x02, 0x00, 0x02, 0x00, + + /* Endpoint descriptor (Bulk In) */ + 0x07, 0x05, 0x82, 0x02, 0x00, 0x02, 0x00 + }; + + /* String Device Framework : + Byte 0 and 1 : Word containing the language ID : 0x0904 for US + Byte 2 : Byte containing the index of the descriptor + Byte 3 : Byte containing the length of the descriptor string + */ + +#define STRING_FRAMEWORK_LENGTH 38 +UCHAR string_framework[] = { + + /* Manufacturer string descriptor : Index 1 */ + 0x09, 0x04, 0x01, 0x0c, + 0x45, 0x78, 0x70, 0x72,0x65, 0x73, 0x20, 0x4c, + 0x6f, 0x67, 0x69, 0x63, + + /* Product string descriptor : Index 2 */ + 0x09, 0x04, 0x02, 0x0c, + 0x44, 0x61, 0x74, 0x61, 0x50, 0x75, 0x6d, 0x70, + 0x44, 0x65, 0x6d, 0x6f, + + /* Serial Number string descriptor : Index 3 */ + 0x09, 0x04, 0x03, 0x04, + 0x30, 0x30, 0x30, 0x31 + }; + + + /* Multiple languages are supported on the device, to add + a language besides English, the unicode language code must + be appended to the language_id_framework array and the length + adjusted accordingly. */ +#define LANGUAGE_ID_FRAMEWORK_LENGTH 2 +UCHAR language_id_framework[] = { + + /* English. */ + 0x09, 0x04 + }; + + +/* Define prototypes for external Host Controller's (HCDs), classes and clients. */ + +VOID tx_demo_instance_activate(VOID *dpump_instance); +VOID tx_demo_instance_deactivate(VOID *dpump_instance); + +UINT _ux_host_class_dpump_entry(UX_HOST_CLASS_COMMAND *command); +UINT ux_hcd_sim_initialize(UX_HCD *hcd); +UINT _ux_host_class_dpump_write(UX_HOST_CLASS_DPUMP *dpump, UCHAR * data_pointer, + ULONG requested_length, ULONG *actual_length); +UINT _ux_host_class_dpump_read (UX_HOST_CLASS_DPUMP *dpump, UCHAR *data_pointer, + ULONG requested_length, ULONG *actual_length); + +TX_THREAD tx_demo_thread_host_simulation; +TX_THREAD tx_demo_thread_slave_simulation; +void tx_demo_thread_host_simulation_entry(ULONG); +void tx_demo_thread_slave_simulation_entry(ULONG); +VOID error_handler(void); + + +/* Define the entry point. */ + +int main() +{ + + /* Enter the ThreadX kernel. */ + tx_kernel_enter(); + + return(0); +} + + +/* Define what the initial system looks like. */ + +void tx_application_define(void *first_unused_memory) +{ + +CHAR *stack_pointer; +CHAR *memory_pointer; +UINT status; +UX_SLAVE_CLASS_DPUMP_PARAMETER parameter; + + + /* Initialize the free memory pointer. */ + stack_pointer = (CHAR *) first_unused_memory; + memory_pointer = stack_pointer + (UX_DEMO_STACK_SIZE * 2); + + /* Initialize USBX Memory. */ + status = ux_system_initialize(memory_pointer, UX_DEMO_MEMORY_SIZE, UX_NULL, 0); + + /* Check for error. */ + if (status != UX_SUCCESS) + error_handler(); + + /* The code below is required for installing the host portion of USBX. */ + status = ux_host_stack_initialize(UX_NULL); + + /* Check for error. */ + if (status != UX_SUCCESS) + error_handler(); + + /* Register all the host class drivers for this USBX implementation. */ + status = ux_host_stack_class_register(_ux_system_host_class_dpump_name, ux_host_class_dpump_entry); + + /* Check for error. */ + if (status != UX_SUCCESS) + error_handler(); + + /* Register all the USB host controllers available in this system */ + status = ux_host_stack_hcd_register(_ux_system_host_hcd_simulator_name, ux_hcd_sim_host_initialize,0,0); + + /* Check for error. */ + if (status != UX_SUCCESS) + error_handler(); + + /* The code below is required for installing the device portion of USBX */ + status = _ux_device_stack_initialize(device_framework_high_speed, DEVICE_FRAMEWORK_LENGTH_HIGH_SPEED, + device_framework_full_speed, DEVICE_FRAMEWORK_LENGTH_FULL_SPEED, + string_framework, STRING_FRAMEWORK_LENGTH, + language_id_framework, LANGUAGE_ID_FRAMEWORK_LENGTH, UX_NULL); + + /* Check for error. */ + if (status != UX_SUCCESS) + error_handler(); + + /* Set the parameters for callback when insertion/extraction of a Data Pump device. */ + parameter.ux_slave_class_dpump_instance_activate = tx_demo_instance_activate; + parameter.ux_slave_class_dpump_instance_deactivate = tx_demo_instance_deactivate; + + /* Initialize the device dpump class. The class is connected with interface 0 */ + status = _ux_device_stack_class_register(_ux_system_slave_class_dpump_name, _ux_device_class_dpump_entry, + 1, 0, ¶meter); + + /* Check for error. */ + if (status != UX_SUCCESS) + error_handler(); + + /* Initialize the simulated device controller. */ + status = _ux_dcd_sim_slave_initialize(); + + /* Check for error. */ + if (status != UX_SUCCESS) + error_handler(); + + /* Create the main host simulation thread. */ + status = tx_thread_create(&tx_demo_thread_host_simulation, "tx demo host simulation", tx_demo_thread_host_simulation_entry, 0, + stack_pointer, UX_DEMO_STACK_SIZE, + 20, 20, 1, TX_AUTO_START); + + /* Check for error. */ + if (status != TX_SUCCESS) + error_handler(); + + /* Create the main demo thread. */ + status = tx_thread_create(&tx_demo_thread_slave_simulation, "tx demo slave simulation", tx_demo_thread_slave_simulation_entry, 0, + stack_pointer + UX_DEMO_STACK_SIZE, UX_DEMO_STACK_SIZE, + 20, 20, 1, TX_AUTO_START); + + /* Check for error. */ + if (status != TX_SUCCESS) + error_handler(); +} + + +void tx_demo_thread_host_simulation_entry(ULONG arg) +{ + +UINT status; +ULONG actual_length; +UCHAR current_char; +UX_HOST_CLASS *class; + + + UX_PARAMETER_NOT_USED(arg); + + /* Find the main data pump container. */ + status = ux_host_stack_class_get(_ux_system_host_class_dpump_name, &class); + + /* Check for error. */ + if (status != UX_SUCCESS) + error_handler(); + + /* We get the first instance of the data pump device. */ + do + { + + status = ux_host_stack_class_instance_get(class, 0, (VOID **) &dpump); + tx_thread_relinquish(); + } while (status != UX_SUCCESS); + + /* We still need to wait for the data pump status to be live. */ + while (dpump -> ux_host_class_dpump_state != UX_HOST_CLASS_INSTANCE_LIVE) + { + + tx_thread_relinquish(); + } + + /* At this point, the data pump class has been found. Now use the + data pump to send and receive data between the host and device. */ + + /* We start with a 'A' in buffer. */ + current_char = 'A'; + + while(1) + { + + /* Increment thread counter. */ + thread_0_counter++; + + /* Initialize the write buffer. */ + _ux_utility_memory_set(host_out_buffer, current_char, UX_HOST_CLASS_DPUMP_PACKET_SIZE); + + /* Increment the character in buffer. */ + current_char++; + + /* Check for upper alphabet limit. */ + if (current_char > 'Z') + current_char = 'A'; + + /* Write to the host Data Pump Bulk out endpoint. */ + status = _ux_host_class_dpump_write (dpump, host_out_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length); + + /* Check for error. */ + if (status != UX_SUCCESS) + error_handler(); + + /* Verify that the status and the amount of data is correct. */ + if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE) + return; + + /* Read to the Data Pump Bulk out endpoint. */ + status = _ux_host_class_dpump_read (dpump, host_in_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length); + + /* Verify that the status and the amount of data is correct. */ + if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE) + error_handler(); + + /* Relinquish to other thread. */ + tx_thread_relinquish(); + } +} + + +void tx_demo_thread_slave_simulation_entry(ULONG arg) +{ + +UINT status; +ULONG actual_length; + + + UX_PARAMETER_NOT_USED(arg); + + while(1) + { + + /* Ensure the dpump class on the device is still alive. */ + while (dpump_slave != UX_NULL) + { + + /* Increment thread counter. */ + thread_1_counter++; + + /* Read from the device data pump. */ + status = _ux_device_class_dpump_read(dpump_slave, slave_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length); + + /* Verify that the status and the amount of data is correct. */ + if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE) + error_handler(); + + /* Now write to the device data pump. */ + status = _ux_device_class_dpump_write(dpump_slave, slave_buffer, UX_HOST_CLASS_DPUMP_PACKET_SIZE, &actual_length); + + /* Verify that the status and the amount of data is correct. */ + if ((status != UX_SUCCESS) || actual_length != UX_HOST_CLASS_DPUMP_PACKET_SIZE) + error_handler(); + } + + /* Relinquish to other thread. */ + tx_thread_relinquish(); + } +} + +VOID tx_demo_instance_activate(VOID *dpump_instance) +{ + + /* Save the DPUMP instance. */ + dpump_slave = (UX_SLAVE_CLASS_DPUMP *) dpump_instance; +} + +VOID tx_demo_instance_deactivate(VOID *dpump_instance) +{ + + UX_PARAMETER_NOT_USED(dpump_instance); + + /* Reset the DPUMP instance. */ + dpump_slave = UX_NULL; +} + + +VOID error_handler(void) +{ + + /* Increment error counter. */ + error_counter++; + + while(1) + { + + /* Error - just spin here! Look at call tree in debugger + to see where the error occurred. */ + } +} + diff --git a/support/usbx_windows_host_files/CDC_ACM_Template.inf b/support/usbx_windows_host_files/CDC_ACM_Template.inf new file mode 100755 index 0000000..0d6a32a --- /dev/null +++ b/support/usbx_windows_host_files/CDC_ACM_Template.inf @@ -0,0 +1,65 @@ +; CDC_ACM.inf +; +; INF file for ExpressLogic simple CDC/ACM class +; +; 1) Replace VID/PID to your own in [MYCORP] section +; VID_vvvv&PID_pppp +; vvvv, pppp: four digit hex number of VID and PID, respectively +; +; 2) Replace 'MYCORP' to your own abbreviated one (without space) +; ex ExpressLogic +; - Replace all MYCORP in this inf file +; +; 3) Replace 'MYDEV000' to your device model number (without space) +; ex CDC ACM Example +; - Replace all MYDEV000 in this inf file +; +; 4) Edit the strings in [Strings] section +; + +[Version] +Signature="$Windows NT$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} + +Provider=%MYCORP% +LayoutFile=layout.inf +DriverVer=08/04/2004,5.1.2600.2180 + +[Manufacturer] +%MYCORP%=MYCORP + +[MYCORP] +%MYDEV000%= MYDEV000,USB\VID_9191&PID_0000 + + +[DestinationDirs] +FakeModemCopyFileSection=12 +DefaultDestDir = 12 + +[MYDEV000.NT] +include=mdmcpq.inf +CopyFiles=FakeModemCopyFileSection +AddReg=MYDEV000.NT.AddReg + +[MYDEV000.NT.Services] +AddService = usbser, 0x00000002, Service_Inst + +[Service_Inst] +DisplayName = %Serial.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %12%\usbser.sys +LoadOrderGroup = Base + +[MYDEV000.NT.AddReg] +HKR,,NTMPDriver,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" +HKR,,PortSubClass,1,01 + +[Strings] +MYCORP = "ExpressLogic" ; Your company name +MYDEV000 = "CDC ACM example device" ; Device description +Serial.SvcDesc = "CDC ACM Driver" ; Device driver description \ No newline at end of file diff --git a/support/usbx_windows_host_files/CDC_ACM_Template_Win7_64bit.inf b/support/usbx_windows_host_files/CDC_ACM_Template_Win7_64bit.inf new file mode 100755 index 0000000..f30b28b --- /dev/null +++ b/support/usbx_windows_host_files/CDC_ACM_Template_Win7_64bit.inf @@ -0,0 +1,66 @@ +; +; This INF file is for linking a USB device that has a specific VID/PID to Windows serial device driver (usbser.sys). +; Where to modify the VID/PID values and various strings is commented below. +; For just getting a device to work, you should only need to modify the VID/PID values. +; + +; +; Modify these strings to change the names displayed for the device. +; + +[Strings] +DriverPackageDisplayName="Express Logic Drivers" +ManufacturerName="Express Logic" +ServiceName="USB RS-232 Emulation Driver" +DeviceName="Express Logic CDC-ACM Device" + +[DefaultInstall] +CopyINF=cdc_acm_elogic.inf + +[Version] +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} +Signature="$Windows NT$" +Provider=%ManufacturerName% +DriverVer=04/01/2014,1.3.0.0 +DriverPackageDisplayName=%DriverPackageDisplayName% + +[Manufacturer] +%ManufacturerName%=DeviceList, NTamd64 + +[DestinationDirs] +FakeModemCopyFileSection=12 +DefaultDestDir=12 + +; +; Change the VID/PID in the following strings 'USB\VID_xxxx&PID_yyyyy&MI_00' to match your USB device. +; For example, if the VID is '8484' and the PID is '0000', the string should be: USB\VID_8484&PID_0000&MI_00 +; + +[DeviceList] +%DeviceName%=DriverInstall, USB\VID_xxxx&PID_yyyy&MI_00 + +[DeviceList.NTamd64] +%DeviceName%=DriverInstall, USB\VID_xxxx&PID_yyyy&MI_00 + +[DriverInstall] +include=mdmcpq.inf,usb.inf +CopyFiles = FakeModemCopyFileSection +AddReg=DriverAddReg + +[DriverAddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[DriverInstall.Services] +include=mdmcpq.inf +AddService=usbser, 0x00000002, DriverService + +[DriverService] +DisplayName=%ServiceName% +ServiceType=1 +StartType=3 +ErrorControl=1 +ServiceBinary=%12%\usbser.sys +LoadOrderGroup=Base diff --git a/support/usbx_windows_host_files/CDC_Composite_Template.inf b/support/usbx_windows_host_files/CDC_Composite_Template.inf new file mode 100755 index 0000000..1114cef --- /dev/null +++ b/support/usbx_windows_host_files/CDC_Composite_Template.inf @@ -0,0 +1,68 @@ +; +; Template INF for a USB CDC Device +; Copyright (c) ExpressLogic +; +[Version] +DriverVer =10/06/1999,5.00.2157.0 +LayoutFile=Layout.inf +Signature="$CHICAGO$" +Class=Modem +ClassGUID={4D36E96D-E325-11CE-BFC1-08002BE10318} +Provider=%Mfg% + + + +[Manufacturer] +%Mfg% = Models + +[ControlFlags] +ExcludeFromSelect=USB\VID_8080&PID_0000&MI_00 + +[DestinationDirs] +FakeModemCopyFileSection=12 +DefaultDestDir=12 + +[Models] +%ELOGIC% = ELOGIC,USB\VID_8080&PID_0000&MI_00 + +[ELOGIC.NT] +include=usb.inf +CopyFiles=FakeModemCopyFileSection +AddReg=USB,ATMEL.resp,ELOGIC.AddReg + +[ELOGIC.NT.Services] +AddService=usbser, 0x00000000, LowerFilter_Service_Inst + +[ELOGIC.NT.HW] +AddReg=LowerFilterAddReg + +[LowerFilterAddReg] +HKR,,"LowerFilters",0x00010000,"usbser" + +[LowerFilter_Service_Inst] +DisplayName=%USBFilterString% +ServiceType= 1 +StartType = 3 +ErrorControl = 0 +ServiceBinary = %12%\usbser.sys + +[FakeModemCopyFileSection] +usbser.sys,,,0x20 + +[Strings] +Mfg = "Express Logic, Inc." +ELOGIC = "Express Logic USB serial emulation" +USBFilterString ="Express Logic USB serial emulation" + +[USB] +HKR,,FriendlyDriver,,Unimodem.vxd +HKR,,DevLoader,,*vcomm +HKR,,ConfigDialog,,serialui.dll +HKR,,AttachedTo,,COM5 +HKR,,EnumPropPages,,"serialui.dll,EnumPropPages" +HKR,,DeviceType, 0, 01 ; +HKR,,PortSubClass,1,02 + +[ELOGIC.AddReg] ;Express Logic USB serial emulation +HKR,, Properties, 1, 00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00, 00,c2,01,00, 00,C2,01,00 + diff --git a/support/usbx_windows_host_files/CDC_ECM_Template.inf b/support/usbx_windows_host_files/CDC_ECM_Template.inf new file mode 100755 index 0000000..2cf7066 --- /dev/null +++ b/support/usbx_windows_host_files/CDC_ECM_Template.inf @@ -0,0 +1,182 @@ +; +; Copyright (c) 2009-2010 Thesycon GmbH +; +; USB CDC ECM Driver setup information file DEMO! +; +; This file supports: +; Windows XP +; Windows Server 2003 +; Windows Vista +; + +;****************************************************************************** +; Version Section +;------------------------------------------------------------------------------ +[Version] +Signature="$Windows NT$" +DriverVer=03/19/2010,1.10.0.0 +Provider=%S_Provider% +CatalogFile=%S_DriverName%.cat + +; private setup class +Class=net +ClassGUID={4d36e972-e325-11ce-bfc1-08002be10318} + + + +;****************************************************************************** +; Manufacturer +;------------------------------------------------------------------------------ +[Manufacturer] +%S_Mfg%=_Models + + +;****************************************************************************** +; Models Section +;------------------------------------------------------------------------------ +[_Models] + +; enter your VID (VVVV) and PID (PPPP) here +%S_DeviceDesc%=_Install,USB\VID_04b4&PID_1128 +; if a multi interface driver is installed enter also the interface number (II) +; %S_DeviceDesc1%=Install,USB\VID_VVVV&PID_PPPP&MI_II +; for more information have a look at the documentation + + +;****************************************************************************** +; Control Flags Sections +;------------------------------------------------------------------------------ +[ControlFlags] +ExcludeFromSelect=* + + +;****************************************************************************** +; Install Sections +;------------------------------------------------------------------------------ +[_Install.NT] +; NCF_PHYSICAL + NCF_HAS_UI +Characteristics = 0x84 +; bus type = PnP Bus: 15 +BusType = 15 +; driver version under XP +DriverVer = 03/19/2010,1.10.0.0 +AddReg = _AddReg_SW +CopyFiles=_CopyFiles_sys + +[_Install.NT.Services] +AddService = %S_ServiceName%, 0x00000002, _AddService, _EventLog + + +[_AddService] +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; MANUAL +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %12%\%S_DriverName%.sys +AddReg=_AddReg_Service + +[_EventLog] +AddReg=_EventLog_AddReg + +[_EventLog_AddReg] +HKR,,EventMessageFile,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\%S_DriverName%.sys" +HKR,,TypesSupported, %REG_DWORD%, 7 + + +;****************************************************************************** +; Registry sections +;------------------------------------------------------------------------------ +[_AddReg_SW] +HKR, Ndi, Service, 0, %S_ServiceName% +HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" +HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" + +; turn of the power management feature +; HKR,,PnPCapabilities,%REG_DWORD%, 0x38 +HKR,,RxBuffers,%REG_DWORD%, 4 +HKR,,TxBuffers,%REG_DWORD%, 4 + +; use this if the device does not report an MAC address +; the device overwrites this value +;HKR,,NetworkAddress,%REG_SZ%, "ACDE48020100" +; set the default media state, 0 is disconnected, 1 is connected +HKR,,DefaultMediaState,%REG_DWORD%, 1 + +; set this key to one of the device ned a one byte termination instead of +; a zero length packet +HKR,,OneByteTermination,%REG_DWORD%, 0 + +; the configuration index for the device +; the Linux gadget may expose the ECM interface on index 1 +HKR,,ConfigurationIndex,%REG_DWORD%, 0 + +; set this to 1 to force the driver to send a clear feature endpoint halt on start +HKR,,SendClearEpHaltOnStart,%REG_DWORD%, 0 + +[_AddReg_Service] +HKR,Parameters,,, + + +;****************************************************************************** +; Copy file sections +;------------------------------------------------------------------------------ +[_CopyFiles_sys] +; Note: no string variable possible in this section ! +; Use COPYFLG_NOVERSIONCHECK for each file to suppress pop-up dialogs if newer files are overwritten. +cdcecm_demo.sys,,,0x00000004 + + +;****************************************************************************** +; Destination Directories +;------------------------------------------------------------------------------ +[DestinationDirs] +DefaultDestDir = 12 ; %windir%\system32\drivers +_CopyFiles_sys = 12 + +;****************************************************************************** +; Disk Layout +;------------------------------------------------------------------------------ +[SourceDisksNames.x86] +1=%S_DiskName%,,0 + +[SourceDisksFiles.x86] +cdcecm_demo.sys=1 +; note: no string variable possible in this section ! + + +;****************************************************************************** +; Strings +;------------------------------------------------------------------------------ +[Strings] +; +; Non-Localizable Strings, DO NOT MODIFY! +; +REG_SZ = 0x00000000 +REG_MULTI_SZ = 0x00010000 +REG_EXPAND_SZ = 0x00020000 +REG_BINARY = 0x00000001 +REG_DWORD = 0x00010001 + + +; +; Localizable Strings, modify as required +; +; provider +S_Provider="ExpressLogic" +S_Mfg="ExpressLogic" + + +; disk name +S_DiskName="CdcEcm driver disk" + +; device description +S_DeviceDesc="ExpressLogic CDC ECM" + +; driver name +S_DriverName="cdcecm_demo" + +; service name +S_ServiceName="cdcecm" + + + +;;;;;;;;;;;;;;;;;;;;;; EOF ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/support/usbx_windows_host_files/RNDIS_Template.inf b/support/usbx_windows_host_files/RNDIS_Template.inf new file mode 100755 index 0000000..2d89a7a --- /dev/null +++ b/support/usbx_windows_host_files/RNDIS_Template.inf @@ -0,0 +1,124 @@ +; +; Template INF for a USB Remote NDIS Device +; Copyright (c) ExpressLogic +; + +[Version] +Signature = "$Windows NT$" +Class = Net +ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} +Provider = %ELogic% +DriverVer = mm/dd/yyyy,x.y.v.z +CatalogFile = ELogic.cat + +[Manufacturer] +%ELogic% = ELogicDevices,NT.5.1 + +[ELogicDevices] +%ELogicDevice% = RNDIS, USB\VID_3939&PID_0000 + +[ELogicDevices.NT.5.1] +%ELogicDevice% = RNDIS.NT.5.1, USB\VID_3939&PID_0000 + +[ControlFlags] +ExcludeFromSelect=* + +; Windows 2000 specific sections --------------------------------- + +[RNDIS.NT] +Characteristics = 0x84 ; NCF_PHYSICAL + NCF_HAS_UI +BusType = 15 +DriverVer = 05/17/2008,0.0.0.0 +AddReg = RNDIS_AddReg_NT, RNDIS_AddReg_WIN2K +CopyFiles = RNDIS_CopyFiles_NT + +; DO NOT MODIFY THE SERVICE NAME +[RNDIS.NT.Services] +AddService = USB_RNDISY, 2, RNDIS_ServiceInst_NT, RNDIS_EventLog + +[RNDIS_CopyFiles_NT] +; no rename of files on Windows 2000, use the 'y' names as is +usb8023y.sys, , , 0 +rndismpy.sys, , , 0 + +[RNDIS_ServiceInst_NT] +DisplayName = %ServiceDisplayName% +ServiceType = 1 +StartType = 3 +ErrorControl = 1 +ServiceBinary = %12%\usb8023y.sys +LoadOrderGroup = NDIS +AddReg = RNDIS_WMI_AddReg_NT + +[RNDIS_WMI_AddReg_NT] +HKR, , MofImagePath, 0x00020000, "System32\drivers\rndismpy.sys" + +; Windows XP specific sections ----------------------------------- + +[RNDIS.NT.5.1] +Characteristics = 0x84 ; NCF_PHYSICAL + NCF_HAS_UI +BusType = 15 +DriverVer = 05/17/2008,0.0.0.0 +AddReg = RNDIS_AddReg_XP +include = netrndis.inf +needs = Usb_Rndis.ndi + +; no copyfiles - the files are already in place + +[RNDIS.NT.5.1.Services] +include = netrndis.inf +needs = Usb_Rndis.ndi.Services + +; Windows 2000 sections + +; DO NOT MODIFY ServiceName +[RNDIS_AddReg_NT] +HKR, Ndi, Service, 0, "USB_RNDISY" +HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" +HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" + +[RNDIS_AddReg_WIN2K] +HKR, , ReclaimRecv, 0x00010001, 1 +HKR, NDI\params\NetworkAddress, ParamDesc, 0, %NetworkAddress% +HKR, NDI\params\NetworkAddress, type, 0, "edit" +HKR, NDI\params\NetworkAddress, LimitText, 0, "12" +HKR, NDI\params\NetworkAddress, UpperCase, 0, "1" +HKR, NDI\params\NetworkAddress, default, 0, " " +HKR, NDI\params\NetworkAddress, optional, 0, "1" + +[RNDIS_EventLog] +AddReg = RNDIS_EventLog_AddReg + +[RNDIS_EventLog_AddReg] +HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll" +HKR, , TypesSupported, 0x00010001, 7 + +; An optional Property to demonstrate adding advanced properties on Windows XP +[RNDIS_AddReg_XP] +HKR, NDI\params\XPProperty, ParamDesc, 0, %Sample_Property% +HKR, NDI\params\XPProperty, type, 0, "edit" +HKR, NDI\params\XPProperty, LimitText, 0, "12" +HKR, NDI\params\XPProperty, UpperCase, 0, "1" +HKR, NDI\params\XPProperty, default, 0, " " +HKR, NDI\params\XPProperty, optional, 0, "1" + + +[SourceDisksNames] +1=%SourceDisk%,,1 + +[SourceDisksFiles] +usb8023y.sys=1 +rndismpy.sys=1 + +[DestinationDirs] +RNDIS_CopyFiles_NT = 12 + +; DO NOT CHANGE ServiceDisplayName +[Strings] +ServiceDisplayName = "USB Remote NDIS Y Network Device Driver" +Sample_Property = "Sample XP property" +NetworkAddress = "Network Address" +ELogic = "ExpressLogic Inc." +ELogicDevice = "ExpressLogic USB Remote NDIS Network Device" +SourceDisk = "ExpressLogic USB Network Driver Install Disk" + diff --git a/usbx_windows_host_files/CDC_ACM_Template.inf b/usbx_windows_host_files/CDC_ACM_Template.inf new file mode 100644 index 0000000..0d6a32a --- /dev/null +++ b/usbx_windows_host_files/CDC_ACM_Template.inf @@ -0,0 +1,65 @@ +; CDC_ACM.inf +; +; INF file for ExpressLogic simple CDC/ACM class +; +; 1) Replace VID/PID to your own in [MYCORP] section +; VID_vvvv&PID_pppp +; vvvv, pppp: four digit hex number of VID and PID, respectively +; +; 2) Replace 'MYCORP' to your own abbreviated one (without space) +; ex ExpressLogic +; - Replace all MYCORP in this inf file +; +; 3) Replace 'MYDEV000' to your device model number (without space) +; ex CDC ACM Example +; - Replace all MYDEV000 in this inf file +; +; 4) Edit the strings in [Strings] section +; + +[Version] +Signature="$Windows NT$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} + +Provider=%MYCORP% +LayoutFile=layout.inf +DriverVer=08/04/2004,5.1.2600.2180 + +[Manufacturer] +%MYCORP%=MYCORP + +[MYCORP] +%MYDEV000%= MYDEV000,USB\VID_9191&PID_0000 + + +[DestinationDirs] +FakeModemCopyFileSection=12 +DefaultDestDir = 12 + +[MYDEV000.NT] +include=mdmcpq.inf +CopyFiles=FakeModemCopyFileSection +AddReg=MYDEV000.NT.AddReg + +[MYDEV000.NT.Services] +AddService = usbser, 0x00000002, Service_Inst + +[Service_Inst] +DisplayName = %Serial.SvcDesc% +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; SERVICE_DEMAND_START +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %12%\usbser.sys +LoadOrderGroup = Base + +[MYDEV000.NT.AddReg] +HKR,,NTMPDriver,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" +HKR,,PortSubClass,1,01 + +[Strings] +MYCORP = "ExpressLogic" ; Your company name +MYDEV000 = "CDC ACM example device" ; Device description +Serial.SvcDesc = "CDC ACM Driver" ; Device driver description \ No newline at end of file diff --git a/usbx_windows_host_files/CDC_ACM_Template_Win7_64bit.inf b/usbx_windows_host_files/CDC_ACM_Template_Win7_64bit.inf new file mode 100644 index 0000000..f30b28b --- /dev/null +++ b/usbx_windows_host_files/CDC_ACM_Template_Win7_64bit.inf @@ -0,0 +1,66 @@ +; +; This INF file is for linking a USB device that has a specific VID/PID to Windows serial device driver (usbser.sys). +; Where to modify the VID/PID values and various strings is commented below. +; For just getting a device to work, you should only need to modify the VID/PID values. +; + +; +; Modify these strings to change the names displayed for the device. +; + +[Strings] +DriverPackageDisplayName="Express Logic Drivers" +ManufacturerName="Express Logic" +ServiceName="USB RS-232 Emulation Driver" +DeviceName="Express Logic CDC-ACM Device" + +[DefaultInstall] +CopyINF=cdc_acm_elogic.inf + +[Version] +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} +Signature="$Windows NT$" +Provider=%ManufacturerName% +DriverVer=04/01/2014,1.3.0.0 +DriverPackageDisplayName=%DriverPackageDisplayName% + +[Manufacturer] +%ManufacturerName%=DeviceList, NTamd64 + +[DestinationDirs] +FakeModemCopyFileSection=12 +DefaultDestDir=12 + +; +; Change the VID/PID in the following strings 'USB\VID_xxxx&PID_yyyyy&MI_00' to match your USB device. +; For example, if the VID is '8484' and the PID is '0000', the string should be: USB\VID_8484&PID_0000&MI_00 +; + +[DeviceList] +%DeviceName%=DriverInstall, USB\VID_xxxx&PID_yyyy&MI_00 + +[DeviceList.NTamd64] +%DeviceName%=DriverInstall, USB\VID_xxxx&PID_yyyy&MI_00 + +[DriverInstall] +include=mdmcpq.inf,usb.inf +CopyFiles = FakeModemCopyFileSection +AddReg=DriverAddReg + +[DriverAddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[DriverInstall.Services] +include=mdmcpq.inf +AddService=usbser, 0x00000002, DriverService + +[DriverService] +DisplayName=%ServiceName% +ServiceType=1 +StartType=3 +ErrorControl=1 +ServiceBinary=%12%\usbser.sys +LoadOrderGroup=Base diff --git a/usbx_windows_host_files/CDC_Composite_Template.inf b/usbx_windows_host_files/CDC_Composite_Template.inf new file mode 100644 index 0000000..1114cef --- /dev/null +++ b/usbx_windows_host_files/CDC_Composite_Template.inf @@ -0,0 +1,68 @@ +; +; Template INF for a USB CDC Device +; Copyright (c) ExpressLogic +; +[Version] +DriverVer =10/06/1999,5.00.2157.0 +LayoutFile=Layout.inf +Signature="$CHICAGO$" +Class=Modem +ClassGUID={4D36E96D-E325-11CE-BFC1-08002BE10318} +Provider=%Mfg% + + + +[Manufacturer] +%Mfg% = Models + +[ControlFlags] +ExcludeFromSelect=USB\VID_8080&PID_0000&MI_00 + +[DestinationDirs] +FakeModemCopyFileSection=12 +DefaultDestDir=12 + +[Models] +%ELOGIC% = ELOGIC,USB\VID_8080&PID_0000&MI_00 + +[ELOGIC.NT] +include=usb.inf +CopyFiles=FakeModemCopyFileSection +AddReg=USB,ATMEL.resp,ELOGIC.AddReg + +[ELOGIC.NT.Services] +AddService=usbser, 0x00000000, LowerFilter_Service_Inst + +[ELOGIC.NT.HW] +AddReg=LowerFilterAddReg + +[LowerFilterAddReg] +HKR,,"LowerFilters",0x00010000,"usbser" + +[LowerFilter_Service_Inst] +DisplayName=%USBFilterString% +ServiceType= 1 +StartType = 3 +ErrorControl = 0 +ServiceBinary = %12%\usbser.sys + +[FakeModemCopyFileSection] +usbser.sys,,,0x20 + +[Strings] +Mfg = "Express Logic, Inc." +ELOGIC = "Express Logic USB serial emulation" +USBFilterString ="Express Logic USB serial emulation" + +[USB] +HKR,,FriendlyDriver,,Unimodem.vxd +HKR,,DevLoader,,*vcomm +HKR,,ConfigDialog,,serialui.dll +HKR,,AttachedTo,,COM5 +HKR,,EnumPropPages,,"serialui.dll,EnumPropPages" +HKR,,DeviceType, 0, 01 ; +HKR,,PortSubClass,1,02 + +[ELOGIC.AddReg] ;Express Logic USB serial emulation +HKR,, Properties, 1, 00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00, 00,00,00,00, 00,c2,01,00, 00,C2,01,00 + diff --git a/usbx_windows_host_files/CDC_ECM_Template.inf b/usbx_windows_host_files/CDC_ECM_Template.inf new file mode 100644 index 0000000..2cf7066 --- /dev/null +++ b/usbx_windows_host_files/CDC_ECM_Template.inf @@ -0,0 +1,182 @@ +; +; Copyright (c) 2009-2010 Thesycon GmbH +; +; USB CDC ECM Driver setup information file DEMO! +; +; This file supports: +; Windows XP +; Windows Server 2003 +; Windows Vista +; + +;****************************************************************************** +; Version Section +;------------------------------------------------------------------------------ +[Version] +Signature="$Windows NT$" +DriverVer=03/19/2010,1.10.0.0 +Provider=%S_Provider% +CatalogFile=%S_DriverName%.cat + +; private setup class +Class=net +ClassGUID={4d36e972-e325-11ce-bfc1-08002be10318} + + + +;****************************************************************************** +; Manufacturer +;------------------------------------------------------------------------------ +[Manufacturer] +%S_Mfg%=_Models + + +;****************************************************************************** +; Models Section +;------------------------------------------------------------------------------ +[_Models] + +; enter your VID (VVVV) and PID (PPPP) here +%S_DeviceDesc%=_Install,USB\VID_04b4&PID_1128 +; if a multi interface driver is installed enter also the interface number (II) +; %S_DeviceDesc1%=Install,USB\VID_VVVV&PID_PPPP&MI_II +; for more information have a look at the documentation + + +;****************************************************************************** +; Control Flags Sections +;------------------------------------------------------------------------------ +[ControlFlags] +ExcludeFromSelect=* + + +;****************************************************************************** +; Install Sections +;------------------------------------------------------------------------------ +[_Install.NT] +; NCF_PHYSICAL + NCF_HAS_UI +Characteristics = 0x84 +; bus type = PnP Bus: 15 +BusType = 15 +; driver version under XP +DriverVer = 03/19/2010,1.10.0.0 +AddReg = _AddReg_SW +CopyFiles=_CopyFiles_sys + +[_Install.NT.Services] +AddService = %S_ServiceName%, 0x00000002, _AddService, _EventLog + + +[_AddService] +ServiceType = 1 ; SERVICE_KERNEL_DRIVER +StartType = 3 ; MANUAL +ErrorControl = 1 ; SERVICE_ERROR_NORMAL +ServiceBinary = %12%\%S_DriverName%.sys +AddReg=_AddReg_Service + +[_EventLog] +AddReg=_EventLog_AddReg + +[_EventLog_AddReg] +HKR,,EventMessageFile,%REG_EXPAND_SZ%,"%%SystemRoot%%\System32\IoLogMsg.dll;%%SystemRoot%%\System32\drivers\%S_DriverName%.sys" +HKR,,TypesSupported, %REG_DWORD%, 7 + + +;****************************************************************************** +; Registry sections +;------------------------------------------------------------------------------ +[_AddReg_SW] +HKR, Ndi, Service, 0, %S_ServiceName% +HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" +HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" + +; turn of the power management feature +; HKR,,PnPCapabilities,%REG_DWORD%, 0x38 +HKR,,RxBuffers,%REG_DWORD%, 4 +HKR,,TxBuffers,%REG_DWORD%, 4 + +; use this if the device does not report an MAC address +; the device overwrites this value +;HKR,,NetworkAddress,%REG_SZ%, "ACDE48020100" +; set the default media state, 0 is disconnected, 1 is connected +HKR,,DefaultMediaState,%REG_DWORD%, 1 + +; set this key to one of the device ned a one byte termination instead of +; a zero length packet +HKR,,OneByteTermination,%REG_DWORD%, 0 + +; the configuration index for the device +; the Linux gadget may expose the ECM interface on index 1 +HKR,,ConfigurationIndex,%REG_DWORD%, 0 + +; set this to 1 to force the driver to send a clear feature endpoint halt on start +HKR,,SendClearEpHaltOnStart,%REG_DWORD%, 0 + +[_AddReg_Service] +HKR,Parameters,,, + + +;****************************************************************************** +; Copy file sections +;------------------------------------------------------------------------------ +[_CopyFiles_sys] +; Note: no string variable possible in this section ! +; Use COPYFLG_NOVERSIONCHECK for each file to suppress pop-up dialogs if newer files are overwritten. +cdcecm_demo.sys,,,0x00000004 + + +;****************************************************************************** +; Destination Directories +;------------------------------------------------------------------------------ +[DestinationDirs] +DefaultDestDir = 12 ; %windir%\system32\drivers +_CopyFiles_sys = 12 + +;****************************************************************************** +; Disk Layout +;------------------------------------------------------------------------------ +[SourceDisksNames.x86] +1=%S_DiskName%,,0 + +[SourceDisksFiles.x86] +cdcecm_demo.sys=1 +; note: no string variable possible in this section ! + + +;****************************************************************************** +; Strings +;------------------------------------------------------------------------------ +[Strings] +; +; Non-Localizable Strings, DO NOT MODIFY! +; +REG_SZ = 0x00000000 +REG_MULTI_SZ = 0x00010000 +REG_EXPAND_SZ = 0x00020000 +REG_BINARY = 0x00000001 +REG_DWORD = 0x00010001 + + +; +; Localizable Strings, modify as required +; +; provider +S_Provider="ExpressLogic" +S_Mfg="ExpressLogic" + + +; disk name +S_DiskName="CdcEcm driver disk" + +; device description +S_DeviceDesc="ExpressLogic CDC ECM" + +; driver name +S_DriverName="cdcecm_demo" + +; service name +S_ServiceName="cdcecm" + + + +;;;;;;;;;;;;;;;;;;;;;; EOF ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/usbx_windows_host_files/RNDIS_Template.inf b/usbx_windows_host_files/RNDIS_Template.inf new file mode 100644 index 0000000..2d89a7a --- /dev/null +++ b/usbx_windows_host_files/RNDIS_Template.inf @@ -0,0 +1,124 @@ +; +; Template INF for a USB Remote NDIS Device +; Copyright (c) ExpressLogic +; + +[Version] +Signature = "$Windows NT$" +Class = Net +ClassGUID = {4d36e972-e325-11ce-bfc1-08002be10318} +Provider = %ELogic% +DriverVer = mm/dd/yyyy,x.y.v.z +CatalogFile = ELogic.cat + +[Manufacturer] +%ELogic% = ELogicDevices,NT.5.1 + +[ELogicDevices] +%ELogicDevice% = RNDIS, USB\VID_3939&PID_0000 + +[ELogicDevices.NT.5.1] +%ELogicDevice% = RNDIS.NT.5.1, USB\VID_3939&PID_0000 + +[ControlFlags] +ExcludeFromSelect=* + +; Windows 2000 specific sections --------------------------------- + +[RNDIS.NT] +Characteristics = 0x84 ; NCF_PHYSICAL + NCF_HAS_UI +BusType = 15 +DriverVer = 05/17/2008,0.0.0.0 +AddReg = RNDIS_AddReg_NT, RNDIS_AddReg_WIN2K +CopyFiles = RNDIS_CopyFiles_NT + +; DO NOT MODIFY THE SERVICE NAME +[RNDIS.NT.Services] +AddService = USB_RNDISY, 2, RNDIS_ServiceInst_NT, RNDIS_EventLog + +[RNDIS_CopyFiles_NT] +; no rename of files on Windows 2000, use the 'y' names as is +usb8023y.sys, , , 0 +rndismpy.sys, , , 0 + +[RNDIS_ServiceInst_NT] +DisplayName = %ServiceDisplayName% +ServiceType = 1 +StartType = 3 +ErrorControl = 1 +ServiceBinary = %12%\usb8023y.sys +LoadOrderGroup = NDIS +AddReg = RNDIS_WMI_AddReg_NT + +[RNDIS_WMI_AddReg_NT] +HKR, , MofImagePath, 0x00020000, "System32\drivers\rndismpy.sys" + +; Windows XP specific sections ----------------------------------- + +[RNDIS.NT.5.1] +Characteristics = 0x84 ; NCF_PHYSICAL + NCF_HAS_UI +BusType = 15 +DriverVer = 05/17/2008,0.0.0.0 +AddReg = RNDIS_AddReg_XP +include = netrndis.inf +needs = Usb_Rndis.ndi + +; no copyfiles - the files are already in place + +[RNDIS.NT.5.1.Services] +include = netrndis.inf +needs = Usb_Rndis.ndi.Services + +; Windows 2000 sections + +; DO NOT MODIFY ServiceName +[RNDIS_AddReg_NT] +HKR, Ndi, Service, 0, "USB_RNDISY" +HKR, Ndi\Interfaces, UpperRange, 0, "ndis5" +HKR, Ndi\Interfaces, LowerRange, 0, "ethernet" + +[RNDIS_AddReg_WIN2K] +HKR, , ReclaimRecv, 0x00010001, 1 +HKR, NDI\params\NetworkAddress, ParamDesc, 0, %NetworkAddress% +HKR, NDI\params\NetworkAddress, type, 0, "edit" +HKR, NDI\params\NetworkAddress, LimitText, 0, "12" +HKR, NDI\params\NetworkAddress, UpperCase, 0, "1" +HKR, NDI\params\NetworkAddress, default, 0, " " +HKR, NDI\params\NetworkAddress, optional, 0, "1" + +[RNDIS_EventLog] +AddReg = RNDIS_EventLog_AddReg + +[RNDIS_EventLog_AddReg] +HKR, , EventMessageFile, 0x00020000, "%%SystemRoot%%\System32\netevent.dll" +HKR, , TypesSupported, 0x00010001, 7 + +; An optional Property to demonstrate adding advanced properties on Windows XP +[RNDIS_AddReg_XP] +HKR, NDI\params\XPProperty, ParamDesc, 0, %Sample_Property% +HKR, NDI\params\XPProperty, type, 0, "edit" +HKR, NDI\params\XPProperty, LimitText, 0, "12" +HKR, NDI\params\XPProperty, UpperCase, 0, "1" +HKR, NDI\params\XPProperty, default, 0, " " +HKR, NDI\params\XPProperty, optional, 0, "1" + + +[SourceDisksNames] +1=%SourceDisk%,,1 + +[SourceDisksFiles] +usb8023y.sys=1 +rndismpy.sys=1 + +[DestinationDirs] +RNDIS_CopyFiles_NT = 12 + +; DO NOT CHANGE ServiceDisplayName +[Strings] +ServiceDisplayName = "USB Remote NDIS Y Network Device Driver" +Sample_Property = "Sample XP property" +NetworkAddress = "Network Address" +ELogic = "ExpressLogic Inc." +ELogicDevice = "ExpressLogic USB Remote NDIS Network Device" +SourceDisk = "ExpressLogic USB Network Driver Install Disk" +