Exemplo n.º 1
0
void system_pending_shutdown()
{
    uint8_t was_set = false;
    system_get_flag(SYSTEM_FLAG_RESET_PENDING, &was_set, nullptr);
    if (!was_set) {
        system_set_flag(SYSTEM_FLAG_RESET_PENDING, 1, nullptr);
        system_notify_event(reset_pending);
    }
}
Exemplo n.º 2
0
int Spark_Prepare_For_Firmware_Update(FileTransfer::Descriptor& file, uint32_t flags, void* reserved)
{
    if (file.store==FileTransfer::Store::FIRMWARE)
    {
        // address is relative to the OTA region. Normally will be 0.
        file.file_address = HAL_OTA_FlashAddress() + file.chunk_address;

        // chunk_size 0 indicates defaults.
        if (file.chunk_size==0) {
            file.chunk_size = HAL_OTA_ChunkSize();
            file.file_length = HAL_OTA_FlashLength();
        }
    }
    int result = 0;
    if (flags & 1) {
        // only check address
    }
    else {
        uint32_t start = HAL_Timer_Milliseconds();
        system_set_flag(SYSTEM_FLAG_OTA_UPDATE_PENDING, 1, nullptr);

        volatile bool flag = false;
        system_notify_event(firmware_update_pending, 0, nullptr, set_flag, (void*)&flag);

        System.waitCondition([&flag]{return flag;}, timeRemaining(start, 30000));

        system_set_flag(SYSTEM_FLAG_OTA_UPDATE_PENDING, 0, nullptr);
        	if (System.updatesEnabled())		// application event is handled asynchronously
        {
            RGB.control(true);
            RGB.color(RGB_COLOR_MAGENTA);
            SPARK_FLASH_UPDATE = 1;
            TimingFlashUpdateTimeout = 0;
            system_notify_event(firmware_update, firmware_update_begin, &file);
            HAL_FLASH_Begin(file.file_address, file.file_length, NULL);
        }
        else
        {
            result = 1;     // updates disabled
        }
    }
    return result;
}
Exemplo n.º 3
0
template<typename Config> void SystemSetupConsole<Config>::handle(char c)
{
    if ('i' == c)
    {
    	// see if we have any additional properties. This is true
    	// for Cellular and Mesh devices.
    	hal_system_info_t info = {};
    	info.size = sizeof(info);
    	HAL_OTA_Add_System_Info(&info, true, nullptr);
    	LOG(TRACE, "device info key/value count: %d", info.key_value_count);
    	if (info.key_value_count) {
    		print("Device ID: ");
    		String id = spark_deviceID();
			print(id.c_str());
			print("\r\n");

			for (int i=0; i<info.key_value_count; i++) {
				char key[20];
				if (!filter_key(info.key_values[i].key, key, sizeof(key))) {
					print(key);
					print(": ");
					print(info.key_values[i].value);
					print("\r\n");
				}
			}
		}
    	else {
	#if PLATFORM_ID<3
			print("Your core id is ");
	#else
			print("Your device id is ");
	#endif
			String id = spark_deviceID();
			print(id.c_str());
			print("\r\n");
    	}
    	HAL_OTA_Add_System_Info(&info, false, nullptr);
    }
    else if ('m' == c)
    {
        print("Your device MAC address is\r\n");
        IPConfig config = {};
    #if !HAL_PLATFORM_WIFI    
        auto conf = static_cast<const IPConfig*>(network_config(0, 0, 0));
    #else
        auto conf = static_cast<const IPConfig*>(network_config(NETWORK_INTERFACE_WIFI_STA, 0, 0));
    #endif
        if (conf && conf->size) {
            memcpy(&config, conf, std::min(sizeof(config), (size_t)conf->size));
        }
        const uint8_t* addr = config.nw.uaMacAddr;
        print(bytes2hex(addr++, 1).c_str());
        for (int i = 1; i < 6; i++)
        {
            print(":");
            print(bytes2hex(addr++, 1).c_str());
        }
        print("\r\n");
    }
    else if ('f' == c)
    {
        serial.println("Waiting for the binary file to be sent ... (press 'a' to abort)");
        system_firmwareUpdate(&serial);
    }
    else if ('x' == c)
    {
        exit();
    }
    else if ('s' == c)
    {
        auto prefix = "{";
        auto suffix = "}\r\n";
        WrappedStreamAppender appender(serial, (const uint8_t*)prefix, strlen(prefix), (const uint8_t*)suffix, strlen(suffix));
        system_module_info(append_instance, &appender);
    }
    else if ('v' == c)
    {
        StreamAppender appender(serial);
        append_system_version_info(&appender);
        print("\r\n");
    }
    else if ('L' == c)
    {
        system_set_flag(SYSTEM_FLAG_STARTUP_LISTEN_MODE, 1, nullptr);
        System.enterSafeMode();
    }
    else if ('c' == c)
    {
            bool claimed = HAL_IsDeviceClaimed(nullptr);
            print("Device claimed: ");
            print(claimed ? "yes" : "no");
            print("\r\n");
    }
    else if ('C' == c)
    {
            char code[64];
            print("Enter 63-digit claim code: ");
            read_line(code, 63);
            if (strlen(code)==63) {
                HAL_Set_Claim_Code(code);
                print("Claim code set to: ");
                print(code);
            }
            else {
                print("Sorry, claim code is not 63 characters long. Claim code unchanged.");
}
        print("\r\n");
    }
    else if ('d' == c)
    {
        system_format_diag_data(nullptr, 0, 0, StreamAppender::append, &serial, nullptr);
        print("\r\n");
    }
}
Exemplo n.º 4
0
uint8_t SystemControlInterface::handleVendorRequest(HAL_USB_SetupRequest* req) {
  /*
   * This callback should process vendor-specific SETUP requests from the host.
   * NOTE: This callback is called from an ISR.
   *
   * Each request contains the following fields:
   * - bmRequestType - request type bit mask. Since only vendor-specific device requests are forwarded
   *                   to this callback, the only bit that should be of intereset is
   *                   "Data Phase Transfer Direction", easily accessed as req->bmRequestTypeDirection:
   *                   0 - Host to Device
   *                   1 - Device to Host
   * - bRequest - 1 byte, request identifier. The only reserved request that will not be forwarded to this callback
   *              is 0xee, which is used for Microsoft-specific vendor requests.
   * - wIndex - 2 byte index, any value between 0x0000 and 0xffff.
   * - wValue - 2 byte value, any value between 0x0000 and 0xffff.
   * - wLength - each request might have an optional data stage of up to 0xffff (65535) bytes.
   *             Host -> Device requests contain data sent by the host to the device.
   *             Device -> Host requests request the device to send up to wLength bytes of data.
   *
   * This callback should return 0 if the request has been correctly handled or 1 otherwise.
   *
   * When handling Device->Host requests with data stage, this callback should fill req->data buffer with
   * up to wLength bytes of data if req->data != NULL (which should be the case when wLength <= 64)
   * or set req->data to point to some buffer which contains up to wLength bytes of data.
   * wLength may be safely modified to notify that there is less data in the buffer than requested by the host.
   *
   * [1] Host -> Device requests with data stage containing up to 64 bytes can be handled by
   * an internal buffer in HAL. For requests larger than 64 bytes, the vendor request callback
   * needs to provide a buffer of an appropriate size:
   *
   * req->data = buffer; // sizeof(buffer) >= req->wLength
   * return 0;
   *
   * The callback will be called again once the data stage completes
   * It will contain the same bmRequest, bRequest, wIndex, wValue and wLength fields.
   * req->data should contain wLength bytes received from the host.
   */

  /*
   * We are handling only bRequest = 0x50 ('P') requests.
   * The request type itself (enum USBRequestType) should be in wIndex field.
   */
  if (req->bRequest != 0x50)
    return 1;

  if (req->bmRequestTypeDirection == 0) {
    // Host -> Device
    switch (req->wIndex) {
      case USB_REQUEST_RESET: {
        // FIXME: We probably shouldn't reset from an ISR.
        // The host will probably get an error that control request has timed out since we
        // didn't respond to it.
        System.reset(req->wValue);
        break;
      }

      case USB_REQUEST_DFU_MODE: {
        // FIXME: We probably shouldn't enter DFU mode from an ISR.
        // The host will probably get an error that control request has timed out since we
        // didn't respond to it.
        System.dfu(false);
        break;
      }

      case USB_REQUEST_LISTENING_MODE: {
        // FIXME: We probably shouldn't enter listening mode from an ISR.
        // The host will probably get an error that control request has timed out since we
        // didn't respond to it.
        system_set_flag(SYSTEM_FLAG_STARTUP_SAFE_LISTEN_MODE, 1, nullptr);
        System.enterSafeMode();
        break;
      }

      case USB_REQUEST_LOG_CONFIG: {
        return enqueueRequest(req, DATA_FORMAT_JSON);
      }

      case USB_REQUEST_CUSTOM: {
        return enqueueRequest(req);
      }

      default: {
        // Unknown request
        return 1;
      }
    }
  } else {
    // Device -> Host
    switch (req->wIndex) {
      case USB_REQUEST_DEVICE_ID: {
        if (req->wLength == 0 || req->data == NULL) {
          // No data stage or requested > 64 bytes
          return 1;
        }
        if (req->wValue == 0x0001) {
          // Return as buffer
          if (req->wLength < 12)
            return 1;

          HAL_device_ID(req->data, req->wLength);
          req->wLength = 12;
        } else {
          // Return as string
          String id = System.deviceID();
          if (req->wLength < (id.length() + 1))
            return 1;
          strncpy((char*)req->data, id.c_str(), req->wLength);
          req->wLength = id.length() + 1;
        }
        break;
      }

      case USB_REQUEST_SYSTEM_VERSION: {
        if (req->wLength == 0 || req->data == NULL) {
          // No data stage or requested > 64 bytes
          return 1;
        }

        strncpy((char*)req->data, __XSTRING(SYSTEM_VERSION_STRING), req->wLength);
        req->wLength = sizeof(__XSTRING(SYSTEM_VERSION_STRING)) + 1;
        break;
      }

      case USB_REQUEST_LOG_CONFIG:
      case USB_REQUEST_CUSTOM: {
        return fetchRequestResult(req);
      }

      default: {
        // Unknown request
        return 1;
      }
    }
  }

  return 0;
}