<commit_before>/*
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "libs/tpu/edgetpu_task.h"

#include <cstdio>
#include <functional>

#include "libs/base/gpio.h"
#include "libs/tpu/edgetpu_manager.h"
#include "libs/tpu/usb_host_edgetpu.h"
#include "libs/usb/usb_host_task.h"

namespace coralmicro {
using namespace edgetpu;

void EdgeTpuTask::SetNextState(EdgeTpuState next_state) {
  Request req;
  req.type = RequestType::kNextState;
  req.request.next_state.state = next_state;
  SendRequestAsync(req);
}

usb_status_t EdgeTpuTask::USBHostEvent(
    usb_host_handle host_handle, usb_device_handle device_handle,
    usb_host_configuration_handle config_handle, uint32_t event_code) {
  usb_host_configuration_t *configuration_ptr;
  uint8_t usb_status = event_code >> 16;
  switch (event_code & 0xFFFF) {
    case kUSB_HostEventAttach:
      configuration_ptr =
          reinterpret_cast<usb_host_configuration_t *>(config_handle);
      for (unsigned int i = 0; i < configuration_ptr->interfaceCount; ++i) {
        auto *interface_ptr = &configuration_ptr->interfaceList[i];
        uint8_t id = interface_ptr->interfaceDesc->bInterfaceClass;

        if (id != USB_HOST_EDGETPU_CLASS_CODE) {
          continue;
        }

        id = interface_ptr->interfaceDesc->bInterfaceSubClass;
        if (id == USB_HOST_EDGETPU_SUBCLASS_CODE) {
          SetDeviceHandle(device_handle);
          SetInterfaceHandle(interface_ptr);
          break;
        }
      }
      return (this->device_handle() != nullptr) ? kStatus_USB_Success
                                                : kStatus_USB_NotSupported;
    case kUSB_HostEventEnumerationDone:
      SetNextState(EdgeTpuState::kAttached);
      return kStatus_USB_Success;
    case kUSB_HostEventDetach:
#if 0
      printf("EdgeTPU went away...\r\n");
#endif
      SetNextState(EdgeTpuState::kUnattached);
      if (auto status = USB_HostEdgeTpuDeinit(this->device_handle(),
                                              this->class_handle());
          status != kStatus_USB_Success) {
        printf("USB_HostEdgeTpuDeinit error: %u\r\n", status);
      }
      if (auto status =
              USB_HostRemoveDevice(host_handle, this->device_handle()) !=
              kStatus_USB_Success) {
        printf("USB_HostRemoveDevice error: %u\r\n", status);
      }
      return kStatus_USB_Success;
    case kUSB_HostEventEnumerationFail:
      printf("%s enumeration failed: %u\r\n", __func__, usb_status);
      SetNextState(EdgeTpuState::kEnumerationFailed);
      return static_cast<usb_status_t>(usb_status);
    default:
      if (usb_status != kStatus_USB_Success) {
        printf("%s failed: %u\r\n", __func__, usb_status);
        SetNextState(EdgeTpuState::kError);
      }
      return static_cast<usb_status_t>(usb_status);
  }
}

void EdgeTpuTask::SetInterfaceCallback(void *param, uint8_t *, uint32_t,
                                       usb_status_t status) {
  auto *task = static_cast<EdgeTpuTask *>(param);
  if (status != kStatus_USB_Success) {
    printf("Error in EdgeTpuSetInterface\r\n");
    task->SetNextState(EdgeTpuState::kError);
    return;
  }
  task->SetNextState(EdgeTpuState::kGetStatus);
}

void EdgeTpuTask::GetStatusCallback(void *param, uint8_t *, uint32_t,
                                    usb_status_t status) {
  auto *task = static_cast<EdgeTpuTask *>(param);
  if (status != kStatus_USB_Success) {
    printf("Error in EdgeTpuGetStatus\r\n");
    task->SetNextState(EdgeTpuState::kError);
    return;
  }
  task->SetNextState(EdgeTpuState::kConnected);
}

void EdgeTpuTask::TaskInit() {
  coralmicro::UsbHostTask::GetSingleton()->RegisterUsbHostEventCallback(
      kEdgeTpuVid, kEdgeTpuPid,
      [this](usb_host_handle host_handle, usb_device_handle device_handle,
             usb_host_configuration_handle config_handle,
             uint32_t event_code) -> _usb_status {
        return EdgeTpuTask::USBHostEvent(host_handle, device_handle,
                                         config_handle, event_code);
      });
}

bool EdgeTpuTask::HandleGetPowerRequest() const { return (enabled_count_ > 0); }

void EdgeTpuTask::HandleSetPowerRequest(SetPowerRequest &req) {
  if (req.enable) {
    enabled_count_++;
    // Already enabled, increment count and exit.<commit_msg>Return to std::bind instead of lambda in EdgeTpuTask<commit_after>/*
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "libs/tpu/edgetpu_task.h"

#include <cstdio>
#include <functional>

#include "libs/base/gpio.h"
#include "libs/tpu/edgetpu_manager.h"
#include "libs/tpu/usb_host_edgetpu.h"
#include "libs/usb/usb_host_task.h"

using namespace std::placeholders;

namespace coralmicro {
using namespace edgetpu;

void EdgeTpuTask::SetNextState(EdgeTpuState next_state) {
  Request req;
  req.type = RequestType::kNextState;
  req.request.next_state.state = next_state;
  SendRequestAsync(req);
}

usb_status_t EdgeTpuTask::USBHostEvent(
    usb_host_handle host_handle, usb_device_handle device_handle,
    usb_host_configuration_handle config_handle, uint32_t event_code) {
  usb_host_configuration_t *configuration_ptr;
  uint8_t usb_status = event_code >> 16;
  switch (event_code & 0xFFFF) {
    case kUSB_HostEventAttach:
      configuration_ptr =
          reinterpret_cast<usb_host_configuration_t *>(config_handle);
      for (unsigned int i = 0; i < configuration_ptr->interfaceCount; ++i) {
        auto *interface_ptr = &configuration_ptr->interfaceList[i];
        uint8_t id = interface_ptr->interfaceDesc->bInterfaceClass;

        if (id != USB_HOST_EDGETPU_CLASS_CODE) {
          continue;
        }

        id = interface_ptr->interfaceDesc->bInterfaceSubClass;
        if (id == USB_HOST_EDGETPU_SUBCLASS_CODE) {
          SetDeviceHandle(device_handle);
          SetInterfaceHandle(interface_ptr);
          break;
        }
      }
      return (this->device_handle() != nullptr) ? kStatus_USB_Success
                                                : kStatus_USB_NotSupported;
    case kUSB_HostEventEnumerationDone:
      SetNextState(EdgeTpuState::kAttached);
      return kStatus_USB_Success;
    case kUSB_HostEventDetach:
#if 0
      printf("EdgeTPU went away...\r\n");
#endif
      SetNextState(EdgeTpuState::kUnattached);
      if (auto status = USB_HostEdgeTpuDeinit(this->device_handle(),
                                              this->class_handle());
          status != kStatus_USB_Success) {
        printf("USB_HostEdgeTpuDeinit error: %u\r\n", status);
      }
      if (auto status =
              USB_HostRemoveDevice(host_handle, this->device_handle()) !=
              kStatus_USB_Success) {
        printf("USB_HostRemoveDevice error: %u\r\n", status);
      }
      return kStatus_USB_Success;
    case kUSB_HostEventEnumerationFail:
      printf("%s enumeration failed: %u\r\n", __func__, usb_status);
      SetNextState(EdgeTpuState::kEnumerationFailed);
      return static_cast<usb_status_t>(usb_status);
    default:
      if (usb_status != kStatus_USB_Success) {
        printf("%s failed: %u\r\n", __func__, usb_status);
        SetNextState(EdgeTpuState::kError);
      }
      return static_cast<usb_status_t>(usb_status);
  }
}

void EdgeTpuTask::SetInterfaceCallback(void *param, uint8_t *, uint32_t,
                                       usb_status_t status) {
  auto *task = static_cast<EdgeTpuTask *>(param);
  if (status != kStatus_USB_Success) {
    printf("Error in EdgeTpuSetInterface\r\n");
    task->SetNextState(EdgeTpuState::kError);
    return;
  }
  task->SetNextState(EdgeTpuState::kGetStatus);
}

void EdgeTpuTask::GetStatusCallback(void *param, uint8_t *, uint32_t,
                                    usb_status_t status) {
  auto *task = static_cast<EdgeTpuTask *>(param);
  if (status != kStatus_USB_Success) {
    printf("Error in EdgeTpuGetStatus\r\n");
    task->SetNextState(EdgeTpuState::kError);
    return;
  }
  task->SetNextState(EdgeTpuState::kConnected);
}

void EdgeTpuTask::TaskInit() {
  coralmicro::UsbHostTask::GetSingleton()->RegisterUsbHostEventCallback(
      kEdgeTpuVid, kEdgeTpuPid,
      std::bind(&EdgeTpuTask::USBHostEvent, this, _1, _2, _3, _4));
}

bool EdgeTpuTask::HandleGetPowerRequest() const { return (enabled_count_ > 0); }

void EdgeTpuTask::HandleSetPowerRequest(SetPowerRequest &req) {
  if (req.enable) {
    enabled_count_++;
    // Already enabled, increment count and exit.
{'fraction_non_alphanumeric': 0.10167703828710052, 'fraction_numerical': 0.00569560172977534, 'mean_word_length': 3.347546996790463, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 54, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 14, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4705405', 'n_tokens_mistral': 2975, 'n_tokens_neox': 2913, 'n_words': 609}