├── Samples └── CurlEasyHttps │ ├── CurlEasyHttps │ ├── applibs_versions.h │ ├── app_manifest.json │ ├── certs │ │ └── DigiCertHighAssuranceEVRootCA.pem │ ├── CurlEasyHttps.vcxproj.filters │ ├── epoll_timerfd_utilities.h │ ├── CurlEasyHttps.vcxproj │ ├── epoll_timerfd_utilities.c │ ├── mt3620_rdb.h │ └── main.c │ └── CurlEasyHttps.sln ├── LICENSE ├── README.md └── .gitignore /Samples/CurlEasyHttps/CurlEasyHttps/applibs_versions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | // This header defines which struct versions will be used for applibs APIs. 3 | #define WIFICONFIG_STRUCTS_VERSION 1 4 | #define UART_STRUCTS_VERSION 1 -------------------------------------------------------------------------------- /Samples/CurlEasyHttps/CurlEasyHttps/app_manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "SchemaVersion": 1, 3 | "Name" : "CurlEasyHttps", 4 | "ComponentId" : "011b3254-6b4e-4af1-bc81-22e7f677f4bf", 5 | "EntryPoint": "/bin/app", 6 | "CmdArgs": [], 7 | "TargetApplicationRuntimeVersion": 1, 8 | "Capabilities": { 9 | "AllowedConnections": [ "example.com" ], 10 | "Gpio": [ 8 ], 11 | "Uart": [], 12 | "WifiConfig": false 13 | } 14 | } -------------------------------------------------------------------------------- /Samples/CurlEasyHttps/CurlEasyHttps.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28105.52 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CurlEasyHttps", "CurlEasyHttps\CurlEasyHttps.vcxproj", "{74BC727B-6B7D-48E1-B600-6296320BC17E}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|ARM = Debug|ARM 11 | Release|ARM = Release|ARM 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {74BC727B-6B7D-48E1-B600-6296320BC17E}.Debug|ARM.ActiveCfg = Debug|ARM 15 | {74BC727B-6B7D-48E1-B600-6296320BC17E}.Debug|ARM.Build.0 = Debug|ARM 16 | {74BC727B-6B7D-48E1-B600-6296320BC17E}.Release|ARM.ActiveCfg = Release|ARM 17 | {74BC727B-6B7D-48E1-B600-6296320BC17E}.Release|ARM.Build.0 = Release|ARM 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {E48DFA9C-552D-4B6A-B07B-F10609A588E3} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Microsoft Corporation. All rights reserved. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /Samples/CurlEasyHttps/CurlEasyHttps/certs/DigiCertHighAssuranceEVRootCA.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs 3 | MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 4 | d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j 5 | ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL 6 | MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 7 | LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug 8 | RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm 9 | +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW 10 | PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM 11 | xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB 12 | Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 13 | hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg 14 | EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF 15 | MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA 16 | FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec 17 | nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z 18 | eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF 19 | hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 20 | Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe 21 | vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep 22 | +OkuE6N36B9K 23 | -----END CERTIFICATE----- 24 | -------------------------------------------------------------------------------- /Samples/CurlEasyHttps/CurlEasyHttps/CurlEasyHttps.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Header Files 23 | 24 | 25 | 26 | Source Files 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | Header Files 35 | 36 | 37 | Header Files 38 | 39 | 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Azure Sphere Samples 3 | This repository contains samples for the [Azure Sphere platform](https://www.microsoft.com/azure-sphere/). 4 | 5 | ## Using the samples 6 | See the [Azure Sphere Getting Started](https://www.microsoft.com/en-us/azure-sphere/get-started/) page for details on getting an [Azure Sphere Development kit](https://aka.ms/AzureSpheredevkits) and setting up your PC for development. You should complete the Azure Sphere [Installation](https://docs.microsoft.com/azure-sphere/install/overview) and [Quickstarts](https://docs.microsoft.com/azure-sphere/quickstarts/qs-overview) to validate that your environment is configured properly before using the samples here. 7 | 8 | Clone this repository locally. Each folder within the samples subdirectory is a self-contained sample. To use a sample open the Visual Studio solution in its folder. You can then build and deploy the sample to your Azure Sphere development kit to learn about the APIs and capabilities it is demonstrating. 9 | 10 | ## Contributing 11 | This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.microsoft.com. 12 | 13 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. 14 | 15 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 16 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or 17 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 18 | -------------------------------------------------------------------------------- /Samples/CurlEasyHttps/CurlEasyHttps/epoll_timerfd_utilities.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | typedef void (*event_handler_t)(void); 7 | 8 | /// 9 | /// Creates an epoll instance. 10 | /// 11 | /// A valid epoll file descriptor on success, or -1 on failure 12 | int CreateEpollFd(void); 13 | 14 | /// 15 | /// Registers an event handler to an epoll instance. 16 | /// 17 | /// Epoll file descriptor 18 | /// File descriptor generating events for the epoll 19 | /// Event handler 20 | /// Bit mask for the epoll event type 21 | /// 0 on success, or -1 on failure 22 | int AddEventHandlerToEpoll(int epollFd, int eventFd, event_handler_t eventHandler, 23 | const uint32_t epollEventMask); 24 | 25 | /// 26 | /// Changes the period of a timerfd. 27 | /// 28 | /// Timer file descriptor 29 | /// The new period 30 | /// 0 on success, or -1 on failure 31 | int SetTimerFdInterval(int timerFd, const struct timespec *period); 32 | 33 | /// 34 | /// Consumes an event by reading from the timer file descriptor. 35 | /// If the event is not consumed, then it will immediately recur. 36 | /// 37 | /// Timer file descriptor 38 | /// 0 on success, or -1 on failure 39 | int ConsumeTimerFdEvent(int timerFd); 40 | 41 | /// 42 | /// Creates a timerfd and adds it to an epoll instance. 43 | /// 44 | /// Epoll file descriptor 45 | /// The timer period 46 | /// Event handler 47 | /// Bit mask for the epoll event type 48 | /// A valid timerfd file descriptor on success, or -1 on failure 49 | int CreateTimerFdAndAddToEpoll(int epollFd, const struct timespec *period, 50 | event_handler_t eventHandler, const uint32_t epollEventMask); 51 | 52 | /// 53 | /// Waits for an event on an epoll instance and triggers the handler. 54 | /// 55 | /// Epoll file descriptor 56 | /// 0 on success, or -1 on failure 57 | int WaitForEventAndCallHandler(int epollFd); 58 | 59 | /// 60 | /// Closes a file descriptor and prints an error on failure. 61 | /// 62 | /// File descriptor to close 63 | /// File descriptor name to use in error message 64 | void CloseFdAndPrintError(int fd, const char *name); -------------------------------------------------------------------------------- /Samples/CurlEasyHttps/CurlEasyHttps/CurlEasyHttps.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | ARM 7 | 8 | 9 | Release 10 | ARM 11 | 12 | 13 | 14 | {74bc727b-6b7d-48e1-b600-6296320bc17e} 15 | AzureSphere 16 | CurlEasyHttps 17 | 15.0 18 | Linux 19 | 1.0 20 | Generic 21 | {D51BCBC9-82E9-4017-911E-C93873C4EA2B} 22 | Device 23 | GCC_AzureSphere_1_0 24 | 25 | 26 | 27 | true 28 | 29 | 30 | false 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | $(IncludePath);$(ISenseIncludePath); 39 | 40 | 41 | $(IncludePath);$(ISenseIncludePath); 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | true 54 | 55 | 56 | 57 | 58 | 59 | 60 | -Werror=implicit-function-declaration %(AdditionalOptions) 61 | 62 | 63 | applibs;pthread;gcc_s;c;curl 64 | -Wl,--no-undefined -nodefaultlibs %(AdditionalOptions) 65 | 66 | 67 | -------------------------------------------------------------------------------- /Samples/CurlEasyHttps/CurlEasyHttps/epoll_timerfd_utilities.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "epoll_timerfd_utilities.h" 7 | 8 | int CreateEpollFd(void) 9 | { 10 | int epollFd = -1; 11 | 12 | epollFd = epoll_create1(0); 13 | if (epollFd == -1) { 14 | Log_Debug("ERROR: Could not create epoll instance: %d (%s)\n", errno, strerror(errno)); 15 | return -1; 16 | } 17 | 18 | return epollFd; 19 | } 20 | 21 | int AddEventHandlerToEpoll(int epollFd, int eventFd, event_handler_t eventHandler, 22 | const uint32_t epollEventMask) 23 | { 24 | struct epoll_event eventToAdd; 25 | eventToAdd.data.ptr = eventHandler; 26 | eventToAdd.events = epollEventMask; 27 | 28 | // Register the eventFd on the epoll instance referred by epollFd 29 | // and register the eventHandler handler for events in epollEventMask 30 | if (epoll_ctl(epollFd, EPOLL_CTL_ADD, eventFd, &eventToAdd) == -1) { 31 | Log_Debug("ERROR: Could not add event to epoll instance %s (%d)\n", strerror(errno), errno); 32 | return -1; 33 | } 34 | 35 | return 0; 36 | } 37 | 38 | int SetTimerFdInterval(int timerFd, const struct timespec *period) 39 | { 40 | struct itimerspec newValue = {}; 41 | newValue.it_value = *period; 42 | newValue.it_interval = *period; 43 | 44 | if (timerfd_settime(timerFd, 0, &newValue, NULL) < 0) { 45 | Log_Debug("ERROR: Could not set timerfd interval %s (%d)\n", strerror(errno), errno); 46 | return -1; 47 | } 48 | 49 | return 0; 50 | } 51 | 52 | int ConsumeTimerFdEvent(int timerFd) 53 | { 54 | uint64_t timerData = 0; 55 | 56 | if (read(timerFd, &timerData, sizeof(timerData)) == -1) { 57 | Log_Debug("ERROR: Could not read timerfd %s (%d)\n", strerror(errno), errno); 58 | return -1; 59 | } 60 | 61 | return 0; 62 | } 63 | 64 | int CreateTimerFdAndAddToEpoll(int epollFd, const struct timespec *period, 65 | event_handler_t eventHandler, const uint32_t epollEventMask) 66 | { 67 | // Create the timerfd and arm it by setting the interval to period 68 | int timerFd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); 69 | if (timerFd < 0) { 70 | Log_Debug("ERROR: Could not create timerfd %s (%d)\n", strerror(errno), errno); 71 | return -1; 72 | } 73 | if (SetTimerFdInterval(timerFd, period) != 0) { 74 | int result = close(timerFd); 75 | if (result != 0) { 76 | Log_Debug("ERROR: Could not close timerfd %s (%d)\n", strerror(errno), errno); 77 | } 78 | return -1; 79 | } 80 | 81 | if (AddEventHandlerToEpoll(epollFd, timerFd, eventHandler, epollEventMask) != 0) { 82 | return -1; 83 | } 84 | 85 | return timerFd; 86 | } 87 | 88 | int WaitForEventAndCallHandler(int epollFd) 89 | { 90 | struct epoll_event event; 91 | int numEventsOccurred = epoll_wait(epollFd, &event, 1, -1); 92 | 93 | if (numEventsOccurred == -1) { 94 | if (errno == EINTR) { 95 | // interrupted by signal, e.g. due to breakpoint being set; ignore 96 | return 0; 97 | } 98 | Log_Debug("ERROR: Failed waiting on events: %s (%d)\n", strerror(errno), errno); 99 | return -1; 100 | } 101 | 102 | if (numEventsOccurred == 1 && event.data.ptr != NULL) { 103 | event_handler_t eventHandler = (event_handler_t)(event.data.ptr); 104 | eventHandler(); 105 | } 106 | 107 | return 0; 108 | } 109 | 110 | void CloseFdAndPrintError(int fd, const char *fdName) 111 | { 112 | if (fd >= 0) { 113 | int result = close(fd); 114 | if (result != 0) { 115 | Log_Debug("WARNING: Could not close fd %s: %s (%d).\n", fdName, strerror(errno), errno); 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /Samples/CurlEasyHttps/CurlEasyHttps/mt3620_rdb.h: -------------------------------------------------------------------------------- 1 | /// This header contains the peripheral pinout definitions for the 2 | /// MT3620 Reference Development Board (RDB) 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | /// LED 1 Red channel is GPIO8. 9 | #define MT3620_RDB_LED1_RED MT3620_GPIO8 10 | 11 | /// LED 1 Green channel is GPIO9. 12 | #define MT3620_RDB_LED1_GREEN MT3620_GPIO9 13 | 14 | /// LED 1 Blue channel is GPIO10. 15 | #define MT3620_RDB_LED1_BLUE MT3620_GPIO10 16 | 17 | /// LED 2 Red channel is GPIO15. 18 | #define MT3620_RDB_LED2_RED MT3620_GPIO15 19 | 20 | /// LED 2 Green channel is GPIO16. 21 | #define MT3620_RDB_LED2_GREEN MT3620_GPIO16 22 | 23 | /// LED 2 Blue channel is GPIO17. 24 | #define MT3620_RDB_LED2_BLUE MT3620_GPIO17 25 | 26 | /// LED 3 Red channel is GPIO18. 27 | #define MT3620_RDB_LED3_RED MT3620_GPIO18 28 | 29 | /// LED 3 Green channel is GPIO19. 30 | #define MT3620_RDB_LED3_GREEN MT3620_GPIO19 31 | 32 | /// LED 3 Blue channel is GPIO20. 33 | #define MT3620_RDB_LED3_BLUE MT3620_GPIO20 34 | 35 | /// LED 4 Red channel is GPIO21. 36 | #define MT3620_RDB_LED4_RED MT3620_GPIO21 37 | 38 | /// LED 4 Green channel is GPIO22. 39 | #define MT3620_RDB_LED4_GREEN MT3620_GPIO22 40 | 41 | /// LED 4 Blue channel is GPIO23. 42 | #define MT3620_RDB_LED4_BLUE MT3620_GPIO23 43 | 44 | /// Status LED Red channel is GPIO45. 45 | #define MT3620_RDB_STATUS_LED_RED MT3620_GPIO45 46 | 47 | /// Status LED Green channel is GPIO46. 48 | #define MT3620_RDB_STATUS_LED_GREEN MT3620_GPIO46 49 | 50 | /// Status LED Blue channel is GPIO47. 51 | #define MT3620_RDB_STATUS_LED_BLUE MT3620_GPIO47 52 | 53 | /// Networking LED Red channel is GPIO48. 54 | #define MT3620_RDB_NETWORKING_LED_RED MT3620_GPIO48 55 | 56 | /// Networking LED Green channel is GPIO14. 57 | #define MT3620_RDB_NETWORKING_LED_GREEN MT3620_GPIO14 58 | 59 | /// Networking LED Blue channel is GPIO11. 60 | #define MT3620_RDB_NETWORKING_LED_BLUE MT3620_GPIO11 61 | 62 | /// Button A is GPIO12. 63 | #define MT3620_RDB_BUTTON_A MT3620_GPIO12 64 | 65 | /// Button B is GPIO13. 66 | #define MT3620_RDB_BUTTON_B MT3620_GPIO13 67 | 68 | // Header 1, pin 1 is SYS_RST 69 | // Header 1, pin 2 is GND 70 | 71 | /// GPIO59 is exposed on header 1, pin 3 72 | #define MT3620_RDB_HEADER1_PIN3_GPIO MT3620_GPIO59 73 | 74 | /// GPIO0 is exposed on header 1, pin 4 75 | #define MT3620_RDB_HEADER1_PIN4_GPIO MT3620_GPIO0 76 | 77 | /// GPIO56 is exposed on header 1, pin 5 78 | #define MT3620_RDB_HEADER1_PIN5_GPIO MT3620_GPIO56 79 | 80 | /// GPIO1 is exposed on header 1, pin 6 81 | #define MT3620_RDB_HEADER1_PIN6_GPIO MT3620_GPIO1 82 | 83 | /// GPIO58 is exposed on header 1, pin 7 84 | #define MT3620_RDB_HEADER1_PIN7_GPIO MT3620_GPIO58 85 | 86 | /// GPIO2 is exposed on header 1, pin 8 87 | #define MT3620_RDB_HEADER1_PIN8_GPIO MT3620_GPIO2 88 | 89 | /// GPIO57 is exposed on header 1, pin 9 90 | #define MT3620_RDB_HEADER1_PIN9_GPIO MT3620_GPIO57 91 | 92 | /// GPIO3 is exposed on header 1, pin 10 93 | #define MT3620_RDB_HEADER1_PIN10_GPIO MT3620_GPIO3 94 | 95 | /// GPIO60 is exposed on header 1, pin 11 96 | #define MT3620_RDB_HEADER1_PIN11_GPIO MT3620_GPIO60 97 | 98 | /// GPIO4 is exposed on header 1, pin 12 99 | #define MT3620_RDB_HEADER1_PIN12_GPIO MT3620_GPIO4 100 | 101 | // Header 2, pins 1, 3, 5, 7 are only supported as the ISU0 UART 102 | #define MT3620_RDB_HEADER2_ISU0_UART MT3620_UART_ISU0 103 | 104 | // Header 2, pin 2 is GND 105 | 106 | /// GPIO5 is exposed on header 2, pin 4 107 | #define MT3620_RDB_HEADER2_PIN4_GPIO MT3620_GPIO5 108 | 109 | /// GPIO6 is exposed on header 2, pin 6 110 | #define MT3620_RDB_HEADER2_PIN6_GPIO MT3620_GPIO6 111 | 112 | /// GPIO7 is exposed on header 2, pin 8 113 | #define MT3620_RDB_HEADER2_PIN8_GPIO MT3620_GPIO7 114 | 115 | /// GPIO30 is exposed on header 2, pin 9 116 | #define MT3620_RDB_HEADER2_PIN9_GPIO MT3620_GPIO30 117 | 118 | // Header 2, pin 10 is ADC VREF 119 | 120 | /// GPIO41 is exposed on header 2, pin 11 121 | #define MT3620_RDB_HEADER2_PIN11_GPIO MT3620_GPIO41 122 | 123 | /// GPIO43 is exposed on header 2, pin 12 124 | #define MT3620_RDB_HEADER2_PIN12_GPIO MT3620_GPIO43 125 | 126 | /// GPIO42 is exposed on header 2, pin 13 127 | #define MT3620_RDB_HEADER2_PIN13_GPIO MT3620_GPIO42 128 | 129 | /// GPIO44 is exposed on header 2, pin 14 130 | #define MT3620_RDB_HEADER2_PIN14_GPIO MT3620_GPIO44 131 | 132 | // Header 3, pin 1 is 5V 133 | // Header 3, pin 2 is GND 134 | // Header 3, pin 3 is 3V3 135 | // Header 3, pin 4 is RTC_WAKEUP 136 | 137 | // Header 3, pin 6 is IO0 UART TX 138 | // Header 3, pin 8 is IO1 UART TX 139 | // Header 3, pin 10 is PMU EN 140 | 141 | // Header 3, pins 5, 7, 9, 11 are only supported as the ISU3 UART 142 | #define MT3620_RDB_HEADER3_ISU3_UART MT3620_UART_ISU3 143 | 144 | /// GPIO70 is exposed on header 3, pin 12 145 | #define MT3620_RDB_HEADER3_PIN12_GPIO MT3620_GPIO70 146 | 147 | // Header 4, pin 1 is SWDIO 148 | // Header 4, pin 2 is GND 149 | // Header 4, pin 3 is SWCLK 150 | // Header 4, pin 4 is SWO 151 | 152 | // Header 4, pins 5, 7, 9, 11 are only supported as the ISU1 UART 153 | #define MT3620_RDB_HEADER4_ISU1_UART MT3620_UART_ISU1 154 | 155 | // Header 4, pins 6, 8, 10, 12 are only supported as the ISU2 UART 156 | #define MT3620_RDB_HEADER4_ISU2_UART MT3620_UART_ISU2 157 | 158 | /// GPIO35 is exposed on header 4, pin 13 159 | #define MT3620_RDB_HEADER4_PIN13_GPIO MT3620_GPIO35 160 | 161 | /// GPIO40 is exposed on header 4, pin 14 162 | #define MT3620_RDB_HEADER4_PIN14_GPIO MT3620_GPIO40 163 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | -------------------------------------------------------------------------------- /Samples/CurlEasyHttps/CurlEasyHttps/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | // applibs_versions.h defines the API struct versions to use for applibs APIs. 9 | #include "applibs_versions.h" 10 | #include 11 | #include 12 | #include 13 | 14 | #include "epoll_timerfd_utilities.h" 15 | 16 | // This sample C application for Azure Sphere periodically downloads and outputs the index web page 17 | // at example.com, by using cURL over a secure HTTPS connection. 18 | // 19 | // It uses the API for the following Azure Sphere application libraries: 20 | // - log (messages shown in Visual Studio's Device Output window during debugging); 21 | // - storage (device storage interaction); 22 | // - curl (web client library). 23 | 24 | static volatile sig_atomic_t terminationRequested = false; 25 | 26 | /// 27 | /// Signal handler for termination requests. This handler must be async-signal-safe. 28 | /// 29 | static void TerminationHandler(int signalNumber) 30 | { 31 | // Don't use Log_Debug here, as it is not guaranteed to be async signal safe 32 | terminationRequested = true; 33 | } 34 | 35 | // Epoll and event handler file descriptors. 36 | static int webpageDownloadTimerFd = -1; 37 | static int epollFd = -1; 38 | 39 | /// 40 | /// Data pointer and size of a block of memory allocated on the heap. 41 | /// 42 | typedef struct { 43 | char *data; 44 | size_t size; 45 | } memory_block_t; 46 | 47 | /// 48 | /// Callback for curl_easy_perform() that copies all the downloaded chunks in a single memory 49 | /// block. 50 | /// The pointer to the chunks array 51 | /// The size of each chunk 52 | /// The count of the chunks 53 | /// The pointer where all the downloaded chunks are aggregated 54 | /// 55 | static size_t StoreDownloadedDataCallback(void *chunks, size_t chunkSize, size_t chunksCount, 56 | void *memoryBlock) 57 | { 58 | memory_block_t *block = (memory_block_t *)memoryBlock; 59 | 60 | size_t additionalDataSize = chunkSize * chunksCount; 61 | block->data = realloc(block->data, block->size + additionalDataSize + 1); 62 | if (block->data == NULL) { 63 | Log_Debug("Out of memory, realloc returned NULL: errno=%d (%s)'n", errno, strerror(errno)); 64 | abort(); 65 | } 66 | 67 | memcpy(block->data + block->size, chunks, additionalDataSize); 68 | block->size += additionalDataSize; 69 | block->data[block->size] = 0; // Ensure the block of memory is null terminated. 70 | 71 | return additionalDataSize; 72 | } 73 | 74 | /// 75 | /// Outputs the reason a cURL function failed using the curl_easy_strerror() utility function. 76 | /// 77 | #define CURL_LOG_STRERROR(message) \ 78 | do { \ 79 | Log_Debug(#message " failed at line %d: %d (%s)\n", __LINE__, res, \ 80 | curl_easy_strerror(res)); \ 81 | } while (false) 82 | 83 | /// 84 | /// Download a web page over HTTPS protocol using cURL. 85 | /// 86 | static void PerformWebPageDownload(void) 87 | { 88 | CURL *curlHandle = NULL; 89 | CURLcode res = 0; 90 | memory_block_t block = {NULL, 0}; 91 | char *certificatePath = NULL; 92 | 93 | bool isNetworkingReady = false; 94 | if ((Networking_IsNetworkingReady(&isNetworkingReady) < 0) || !isNetworkingReady) { 95 | Log_Debug("\n\nNot doing download because network is not up.\n\n"); 96 | goto exitLabel; 97 | } 98 | 99 | Log_Debug("\n\n -===- Starting downloading -===-\n\n"); 100 | 101 | // Init the cURL library. 102 | if ((res = curl_global_init(CURL_GLOBAL_ALL)) != CURLE_OK) { 103 | CURL_LOG_STRERROR(curl_global_init); 104 | goto exitLabel; 105 | } 106 | 107 | if ((curlHandle = curl_easy_init()) == NULL) { 108 | Log_Debug("curl_easy_init() failed\n"); 109 | goto cleanupLabel; 110 | } 111 | 112 | // Specify URL to download. 113 | // Important: any change in the domain name must be reflected in the AllowedConnections 114 | // capability in app_manifest.json. 115 | if ((res = curl_easy_setopt(curlHandle, CURLOPT_URL, "https://example.com")) != CURLE_OK) { 116 | CURL_LOG_STRERROR(curl_reasy_setopt); 117 | goto cleanupLabel; 118 | } 119 | 120 | // Set output level to verbose. 121 | if ((res = curl_easy_setopt(curlHandle, CURLOPT_VERBOSE, 1L)) != CURLE_OK) { 122 | CURL_LOG_STRERROR(curl_easy_setopt); 123 | goto cleanupLabel; 124 | } 125 | 126 | // Get the full path to the certificate file used to authenticate the HTTPS server identity. 127 | // The DigiCertHighAssuranceEVRootCA.pem file is the certificate that is used to verify the 128 | // server identity. 129 | certificatePath = 130 | Storage_GetAbsolutePathInImagePackage("certs/DigiCertHighAssuranceEVRootCA.pem"); 131 | if (certificatePath == NULL) { 132 | Log_Debug("The certificate path could not be resolved: errno=%d (%s)\n", errno, 133 | strerror(errno)); 134 | goto cleanupLabel; 135 | } 136 | 137 | // Set the path for the certificate file that cURL uses to validate the server certificate. 138 | if ((res = curl_easy_setopt(curlHandle, CURLOPT_CAINFO, certificatePath)) != CURLE_OK) { 139 | CURL_LOG_STRERROR(curl_easy_setopt); 140 | goto cleanupLabel; 141 | } 142 | 143 | // Let cURL follow any HTTP 3xx redirects. 144 | // Important: any redirection to different domain names requires that domain name to be added to 145 | // app_manifest.json. 146 | if ((res = curl_easy_setopt(curlHandle, CURLOPT_FOLLOWLOCATION, 1L)) != CURLE_OK) { 147 | CURL_LOG_STRERROR(curl_easy_setopt); 148 | goto cleanupLabel; 149 | } 150 | 151 | // Set up callback for cURL to use when downloading data. 152 | if ((res = curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, StoreDownloadedDataCallback)) != 153 | CURLE_OK) { 154 | CURL_LOG_STRERROR(curl_easy_setopt); 155 | goto cleanupLabel; 156 | } 157 | 158 | // Set the custom parameter of the callback to the memory block. 159 | if ((res = curl_easy_setopt(curlHandle, CURLOPT_WRITEDATA, (void *)&block)) != CURLE_OK) { 160 | CURL_LOG_STRERROR(curl_easy_setopt); 161 | goto cleanupLabel; 162 | } 163 | 164 | // Specify a user agent. 165 | if ((res = curl_easy_setopt(curlHandle, CURLOPT_USERAGENT, "libcurl-agent/1.0")) != CURLE_OK) { 166 | CURL_LOG_STRERROR(curl_easy_setopt); 167 | goto cleanupLabel; 168 | } 169 | 170 | // Perform the download of the web page. 171 | if ((res = curl_easy_perform(curlHandle)) != CURLE_OK) { 172 | CURL_LOG_STRERROR(curl_easy_perform); 173 | } else { 174 | Log_Debug("\n\n -===- Downloaded content (%lu bytes): -===-\n\n", block.size); 175 | Log_Debug("%s\n", block.data); 176 | } 177 | 178 | cleanupLabel: 179 | // Clean up allocated memory. 180 | free(block.data); 181 | free(certificatePath); 182 | // Clean up sample's cURL resources. 183 | curl_easy_cleanup(curlHandle); 184 | // Clean up cURL library's resources. 185 | curl_global_cleanup(); 186 | 187 | exitLabel: 188 | return; 189 | } 190 | 191 | /// 192 | /// The timer event handler. 193 | /// 194 | static void TimerEventHandler(void) 195 | { 196 | if (ConsumeTimerFdEvent(webpageDownloadTimerFd) != 0) { 197 | terminationRequested = true; 198 | return; 199 | } 200 | 201 | PerformWebPageDownload(); 202 | } 203 | 204 | /// 205 | /// Initialization of the sample includes the following: 206 | /// - set up a SIGTERM termination handler; 207 | /// - set up an epoll instance; 208 | /// - set up a timer event. 209 | /// 210 | /// 0 on success, or -1 on failure 211 | static int Init(void) 212 | { 213 | struct sigaction action; 214 | memset(&action, 0, sizeof(struct sigaction)); 215 | action.sa_handler = TerminationHandler; 216 | sigaction(SIGTERM, &action, NULL); 217 | 218 | epollFd = CreateEpollFd(); 219 | if (epollFd < 0) { 220 | return -1; 221 | } 222 | 223 | // Issue an HTTPS request at the specified period. 224 | struct timespec tenSeconds = {10, 0}; 225 | webpageDownloadTimerFd = 226 | CreateTimerFdAndAddToEpoll(epollFd, &tenSeconds, &TimerEventHandler, EPOLLIN); 227 | if (webpageDownloadTimerFd < 0) { 228 | return -1; 229 | } 230 | 231 | return 0; 232 | } 233 | 234 | /// 235 | /// Clean up the resources previously allocated. 236 | /// 237 | static void Cleanup(void) 238 | { 239 | Log_Debug("Closing file descriptors\n"); 240 | 241 | // Close the timer and epoll file descriptors. 242 | CloseFdAndPrintError(webpageDownloadTimerFd, "WebpageDownloadTimer"); 243 | CloseFdAndPrintError(epollFd, "Epoll"); 244 | } 245 | 246 | // 247 | /// Main entry point for this sample. 248 | /// 249 | int main(int argc, char *argv[]) 250 | { 251 | Log_Debug("cURL HTTPS application starting\n"); 252 | 253 | if (Init() != 0) { 254 | terminationRequested = true; 255 | } 256 | 257 | // Download the web page immediately. 258 | PerformWebPageDownload(); 259 | 260 | // Use epoll to wait for events and trigger handlers, until an error or SIGTERM happens 261 | // Periodically downloads the web page. 262 | while (!terminationRequested) { 263 | if (WaitForEventAndCallHandler(epollFd) != 0) { 264 | terminationRequested = true; 265 | } 266 | } 267 | 268 | Cleanup(); 269 | Log_Debug("Application exiting\n"); 270 | return 0; 271 | } --------------------------------------------------------------------------------