Skip to content

Extend bus types and structure for Peripheral Manager #8888

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Extended bus types for peripheral manager
  • Loading branch information
P-R-O-C-H-Y committed Nov 15, 2023
commit 854377390b4f7529757db0651cf0d1bdab954a01
6 changes: 3 additions & 3 deletions cores/esp32/HWCDC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,10 +220,10 @@ void HWCDC::begin(unsigned long baud)
end();
return;
}
if (perimanSetBusDeinit(ESP32_BUS_TYPE_USB, HWCDC::deinit)) {
if (perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DM, HWCDC::deinit) && perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DP, HWCDC::deinit)) {
// Setting USB D+ D- pins
perimanSetPinBus(USB_DM_GPIO_NUM, ESP32_BUS_TYPE_USB, (void *) this);
perimanSetPinBus(USB_DP_GPIO_NUM, ESP32_BUS_TYPE_USB, (void *) this);
perimanSetPinBus(USB_DM_GPIO_NUM, ESP32_BUS_TYPE_USB_DM, (void *) this);
perimanSetPinBus(USB_DP_GPIO_NUM, ESP32_BUS_TYPE_USB_DP, (void *) this);
} else {
log_e("Serial JTAG Pins can't be set into Peripheral Manager.");
}
Expand Down
6 changes: 4 additions & 2 deletions cores/esp32/esp32-hal-i2c-slave.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,9 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t
frequency = 1000000;
}

perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_SLAVE, i2cSlaveDetachBus);
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_SLAVE_SDA, i2cSlaveDetachBus);
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_SLAVE_SCL, i2cSlaveDetachBus);

if(!perimanSetPinBus(sda, ESP32_BUS_TYPE_INIT, NULL) || !perimanSetPinBus(scl, ESP32_BUS_TYPE_INIT, NULL)){
return false;
}
Expand Down Expand Up @@ -353,7 +355,7 @@ esp_err_t i2cSlaveInit(uint8_t num, int sda, int scl, uint16_t slaveID, uint32_t
i2c_ll_slave_enable_rx_it(i2c->dev);
i2c_ll_set_stretch(i2c->dev, 0x3FF);
i2c_ll_update(i2c->dev);
if(!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_SLAVE, (void *)(i2c->num+1)) || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_SLAVE, (void *)(i2c->num+1))){
if(!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_SLAVE_SDA, (void *)(i2c->num+1)) || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_SLAVE_SCL, (void *)(i2c->num+1))){
i2cSlaveDetachBus((void *)(i2c->num+1));
ret = ESP_FAIL;
}
Expand Down
6 changes: 4 additions & 2 deletions cores/esp32/esp32-hal-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency){
frequency = 1000000UL;
}

perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER, i2cDetachBus);
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SDA, i2cDetachBus);
perimanSetBusDeinit(ESP32_BUS_TYPE_I2C_MASTER_SCL, i2cDetachBus);

if(!perimanSetPinBus(sda, ESP32_BUS_TYPE_INIT, NULL) || !perimanSetPinBus(scl, ESP32_BUS_TYPE_INIT, NULL)){
return false;
}
Expand Down Expand Up @@ -128,7 +130,7 @@ esp_err_t i2cInit(uint8_t i2c_num, int8_t sda, int8_t scl, uint32_t frequency){
bus[i2c_num].sda = sda;
//Clock Stretching Timeout: 20b:esp32, 5b:esp32-c3, 24b:esp32-s2
i2c_set_timeout((i2c_port_t)i2c_num, I2C_LL_MAX_TIMEOUT);
if(!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_MASTER, (void *)(i2c_num+1)) || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_MASTER, (void *)(i2c_num+1))){
if(!perimanSetPinBus(sda, ESP32_BUS_TYPE_I2C_MASTER_SDA, (void *)(i2c_num+1)) || !perimanSetPinBus(scl, ESP32_BUS_TYPE_I2C_MASTER_SCL, (void *)(i2c_num+1))){
i2cDetachBus((void *)(i2c_num+1));
return false;
}
Expand Down
53 changes: 44 additions & 9 deletions cores/esp32/esp32-hal-periman.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,26 +46,61 @@ const char* perimanGetTypeName(peripheral_bus_type_t type) {
case ESP32_BUS_TYPE_RMT_RX: return "RMT_RX";
#endif
#if SOC_I2S_SUPPORTED
case ESP32_BUS_TYPE_I2S_STD: return "I2S_STD";
case ESP32_BUS_TYPE_I2S_TDM: return "I2S_TDM";
case ESP32_BUS_TYPE_I2S_PDM_TX: return "I2S_PDM_TX";
case ESP32_BUS_TYPE_I2S_PDM_RX: return "I2S_PDM_RX";
case ESP32_BUS_TYPE_I2S_STD_MCLK: return "I2S_STD_MCLK";
case ESP32_BUS_TYPE_I2S_STD_BCLK: return "I2S_STD_BCLK";
case ESP32_BUS_TYPE_I2S_STD_WS: return "I2S_STD_WS";
case ESP32_BUS_TYPE_I2S_STD_DOUT: return "I2S_STD_DOUT";
case ESP32_BUS_TYPE_I2S_STD_DIN: return "I2S_STD_DIN";
case ESP32_BUS_TYPE_I2S_TDM_MCLK: return "I2S_TDM_MCLK";
case ESP32_BUS_TYPE_I2S_TDM_BCLK: return "I2S_TDM_BCLK";
case ESP32_BUS_TYPE_I2S_TDM_WS: return "I2S_TDM_WS";
case ESP32_BUS_TYPE_I2S_TDM_DOUT: return "I2S_TDM_DOUT";
case ESP32_BUS_TYPE_I2S_TDM_DIN: return "I2S_TDM_DIN";
case ESP32_BUS_TYPE_I2S_PDM_TX_CLK: return "I2S_PDM_TX_CLK";
case ESP32_BUS_TYPE_I2S_PDM_TX_DOUT0: return "I2S_PDM_TX_DOUT0";
case ESP32_BUS_TYPE_I2S_PDM_TX_DOUT1: return "I2S_PDM_TX_DOUT1";
case ESP32_BUS_TYPE_I2S_PDM_RX_CLK: return "I2S_PDM_RX_CLK";
case ESP32_BUS_TYPE_I2S_PDM_RX_DIN0: return "I2S_PDM_RX_DIN0";
case ESP32_BUS_TYPE_I2S_PDM_RX_DIN1: return "I2S_PDM_RX_DIN1";
case ESP32_BUS_TYPE_I2S_PDM_RX_DIN2: return "I2S_PDM_RX_DIN2";
case ESP32_BUS_TYPE_I2S_PDM_RX_DIN3: return "I2S_PDM_RX_DIN3";
#endif
#if SOC_I2C_SUPPORTED
case ESP32_BUS_TYPE_I2C_MASTER: return "I2C_MASTER";
case ESP32_BUS_TYPE_I2C_SLAVE: return "I2C_SLAVE";
case ESP32_BUS_TYPE_I2C_MASTER_SDA: return "I2C_MASTER_SDA";
case ESP32_BUS_TYPE_I2C_MASTER_SCL: return "I2C_MASTER_SCL";
case ESP32_BUS_TYPE_I2C_SLAVE_SDA: return "I2C_SLAVE_SDA";
case ESP32_BUS_TYPE_I2C_SLAVE_SCL: return "I2C_SLAVE_SCL";
#endif
#if SOC_GPSPI_SUPPORTED
case ESP32_BUS_TYPE_SPI_MASTER: return "SPI_MASTER";
case ESP32_BUS_TYPE_SPI_MASTER_SCK: return "SPI_MASTER_SCK";
case ESP32_BUS_TYPE_SPI_MASTER_MISO: return "SPI_MASTER_MISO";
case ESP32_BUS_TYPE_SPI_MASTER_MOSI: return "SPI_MASTER_MOSI";
case ESP32_BUS_TYPE_SPI_MASTER_CS: return "SPI_MASTER_CS";
#endif
#if SOC_SDMMC_HOST_SUPPORTED
case ESP32_BUS_TYPE_SDMMC: return "SDMMC";
case ESP32_BUS_TYPE_SDMMC_CLK: return "SDMMC_CLK";
case ESP32_BUS_TYPE_SDMMC_CMD: return "SDMMC_CMD";
case ESP32_BUS_TYPE_SDMMC_D0: return "SDMMC_D0";
case ESP32_BUS_TYPE_SDMMC_D1: return "SDMMC_D1";
case ESP32_BUS_TYPE_SDMMC_D2: return "SDMMC_D2";
case ESP32_BUS_TYPE_SDMMC_D3: return "SDMMC_D3";
#endif
#if SOC_TOUCH_SENSOR_SUPPORTED
case ESP32_BUS_TYPE_TOUCH: return "TOUCH";
#endif
#if SOC_USB_SERIAL_JTAG_SUPPORTED || SOC_USB_OTG_SUPPORTED
case ESP32_BUS_TYPE_USB: return "USB";
case ESP32_BUS_TYPE_USB_DM: return "USB_DM";
case ESP32_BUS_TYPE_USB_DP: return "USB_DP";
#endif
#if SOC_GPSPI_SUPPORTED
case ESP32_BUS_TYPE_ETHERNET_SPI: return "ETHERNET_SPI";
#endif
#if CONFIG_ETH_USE_ESP32_EMAC
case ESP32_BUS_TYPE_ETHERNET_RMII: return "ETHERNET_RMII";
case ESP32_BUS_TYPE_ETHERNET_CLK: return "ETHERNET_CLK";
case ESP32_BUS_TYPE_ETHERNET_MCD: return "ETHERNET_MCD";
case ESP32_BUS_TYPE_ETHERNET_MDIO: return "ETHERNET_MDIO";
case ESP32_BUS_TYPE_ETHERNET_PWR: return "ETHERNET_PWR";
#endif
default: return "UNKNOWN";
}
Expand Down
55 changes: 45 additions & 10 deletions cores/esp32/esp32-hal-periman.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,29 +41,64 @@ typedef enum {
ESP32_BUS_TYPE_RMT_RX, // IO is used as RMT input
#endif
#if SOC_I2S_SUPPORTED
ESP32_BUS_TYPE_I2S_STD, // IO is used as I2S STD pin
ESP32_BUS_TYPE_I2S_TDM, // IO is used as I2S TDM pin
ESP32_BUS_TYPE_I2S_PDM_TX, // IO is used as I2S PDM pin
ESP32_BUS_TYPE_I2S_PDM_RX, // IO is used as I2S PDM pin
ESP32_BUS_TYPE_I2S_STD_MCLK, // IO is used as I2S STD MCLK pin
ESP32_BUS_TYPE_I2S_STD_BCLK, // IO is used as I2S STD BCLK pin
ESP32_BUS_TYPE_I2S_STD_WS, // IO is used as I2S STD WS pin
ESP32_BUS_TYPE_I2S_STD_DOUT, // IO is used as I2S STD DOUT pin
ESP32_BUS_TYPE_I2S_STD_DIN, // IO is used as I2S STD DIN pin

ESP32_BUS_TYPE_I2S_TDM_MCLK, // IO is used as I2S TDM MCLK pin
ESP32_BUS_TYPE_I2S_TDM_BCLK, // IO is used as I2S TDM BCLK pin
ESP32_BUS_TYPE_I2S_TDM_WS, // IO is used as I2S TDM WS pin
ESP32_BUS_TYPE_I2S_TDM_DOUT, // IO is used as I2S TDM DOUT pin
ESP32_BUS_TYPE_I2S_TDM_DIN, // IO is used as I2S TDM DIN pin

ESP32_BUS_TYPE_I2S_PDM_TX_CLK, // IO is used as I2S PDM CLK pin
ESP32_BUS_TYPE_I2S_PDM_TX_DOUT0,// IO is used as I2S PDM DOUT0 pin
ESP32_BUS_TYPE_I2S_PDM_TX_DOUT1,// IO is used as I2S PDM DOUT1 pin

ESP32_BUS_TYPE_I2S_PDM_RX_CLK, // IO is used as I2S PDM CLK pin
ESP32_BUS_TYPE_I2S_PDM_RX_DIN0, // IO is used as I2S PDM DIN0 pin
ESP32_BUS_TYPE_I2S_PDM_RX_DIN1, // IO is used as I2S PDM DIN1 pin
ESP32_BUS_TYPE_I2S_PDM_RX_DIN2, // IO is used as I2S PDM DIN2 pin
ESP32_BUS_TYPE_I2S_PDM_RX_DIN3, // IO is used as I2S PDM DIN3 pin
#endif
#if SOC_I2C_SUPPORTED
ESP32_BUS_TYPE_I2C_MASTER, // IO is used as I2C master pin
ESP32_BUS_TYPE_I2C_SLAVE, // IO is used as I2C slave pin
ESP32_BUS_TYPE_I2C_MASTER_SDA, // IO is used as I2C master SDA pin
ESP32_BUS_TYPE_I2C_MASTER_SCL, // IO is used as I2C master SCL pin
ESP32_BUS_TYPE_I2C_SLAVE_SDA, // IO is used as I2C slave SDA pin
ESP32_BUS_TYPE_I2C_SLAVE_SCL, // IO is used as I2C slave SCL pin
#endif
#if SOC_GPSPI_SUPPORTED
ESP32_BUS_TYPE_SPI_MASTER, // IO is used as SPI master pin
ESP32_BUS_TYPE_SPI_MASTER_SCK, // IO is used as SPI master SCK pin
ESP32_BUS_TYPE_SPI_MASTER_MISO, // IO is used as SPI master MISO pin
ESP32_BUS_TYPE_SPI_MASTER_MOSI, // IO is used as SPI master MOSI pin
ESP32_BUS_TYPE_SPI_MASTER_CS, // IO is used as SPI master CS pin
#endif
#if SOC_SDMMC_HOST_SUPPORTED
ESP32_BUS_TYPE_SDMMC, // IO is used as SDMMC pin
ESP32_BUS_TYPE_SDMMC_CLK, // IO is used as SDMMC CLK pin
ESP32_BUS_TYPE_SDMMC_CMD, // IO is used as SDMMC CMD pin
ESP32_BUS_TYPE_SDMMC_D0, // IO is used as SDMMC D0 pin
ESP32_BUS_TYPE_SDMMC_D1, // IO is used as SDMMC D1 pin
ESP32_BUS_TYPE_SDMMC_D2, // IO is used as SDMMC D2 pin
ESP32_BUS_TYPE_SDMMC_D3, // IO is used as SDMMC D3 pin
#endif
#if SOC_TOUCH_SENSOR_SUPPORTED
ESP32_BUS_TYPE_TOUCH, // IO is used as TOUCH pin
#endif
#if SOC_USB_SERIAL_JTAG_SUPPORTED || SOC_USB_OTG_SUPPORTED
ESP32_BUS_TYPE_USB, // IO is used as USB pin
ESP32_BUS_TYPE_USB_DM, // IO is used as USB DM (+) pin
ESP32_BUS_TYPE_USB_DP, // IO is used as USB DP (-) pin
#endif
#if SOC_GPSPI_SUPPORTED
ESP32_BUS_TYPE_ETHERNET, // IO is used as ETHERNET-RMII pin
ESP32_BUS_TYPE_ETHERNET_SPI, // IO is used as dedicated ETHERNET-RMII pin
#endif
#if CONFIG_ETH_USE_ESP32_EMAC
ESP32_BUS_TYPE_ETHERNET_RMII, // IO is used as dedicated ETHERNET-RMII pin
ESP32_BUS_TYPE_ETHERNET_CLK, // IO is used as ETHERNET CLK pin
ESP32_BUS_TYPE_ETHERNET_MCD, // IO is used as ETHERNET MCD pin
ESP32_BUS_TYPE_ETHERNET_MDIO, // IO is used as ETHERNET MDIO pin
ESP32_BUS_TYPE_ETHERNET_PWR, // IO is used as ETHERNET PWR pin
#endif
ESP32_BUS_TYPE_MAX
} peripheral_bus_type_t;
Expand Down
22 changes: 13 additions & 9 deletions cores/esp32/esp32-hal-spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,14 +205,14 @@ bool spiAttachSCK(spi_t * spi, int8_t sck)
if(!spi || sck < 0) {
return false;
}
void * bus = perimanGetPinBus(sck, ESP32_BUS_TYPE_SPI_MASTER);
void * bus = perimanGetPinBus(sck, ESP32_BUS_TYPE_SPI_MASTER_SCK);
if(bus != NULL && !perimanSetPinBus(sck, ESP32_BUS_TYPE_INIT, NULL)){
return false;
}
pinMode(sck, OUTPUT);
pinMatrixOutAttach(sck, SPI_CLK_IDX(spi->num), false, false);
spi->sck = sck;
if(!perimanSetPinBus(sck, ESP32_BUS_TYPE_SPI_MASTER, (void *)(spi->num+1))){
if(!perimanSetPinBus(sck, ESP32_BUS_TYPE_SPI_MASTER_SCK, (void *)(spi->num+1))){
spiDetachBus((void *)(spi->num+1));
log_e("Failed to set pin bus to SPI for pin %d", sck);
return false;
Expand All @@ -225,7 +225,7 @@ bool spiAttachMISO(spi_t * spi, int8_t miso)
if(!spi || miso < 0) {
return false;
}
void * bus = perimanGetPinBus(miso, ESP32_BUS_TYPE_SPI_MASTER);
void * bus = perimanGetPinBus(miso, ESP32_BUS_TYPE_SPI_MASTER_MISO);
if(bus != NULL && !perimanSetPinBus(miso, ESP32_BUS_TYPE_INIT, NULL)){
return false;
}
Expand All @@ -234,7 +234,7 @@ bool spiAttachMISO(spi_t * spi, int8_t miso)
pinMatrixInAttach(miso, SPI_MISO_IDX(spi->num), false);
spi->miso = miso;
SPI_MUTEX_UNLOCK();
if(!perimanSetPinBus(miso, ESP32_BUS_TYPE_SPI_MASTER, (void *)(spi->num+1))){
if(!perimanSetPinBus(miso, ESP32_BUS_TYPE_SPI_MASTER_MISO, (void *)(spi->num+1))){
spiDetachBus((void *)(spi->num+1));
log_e("Failed to set pin bus to SPI for pin %d", miso);
return false;
Expand All @@ -247,14 +247,14 @@ bool spiAttachMOSI(spi_t * spi, int8_t mosi)
if(!spi || mosi < 0) {
return false;
}
void * bus = perimanGetPinBus(mosi, ESP32_BUS_TYPE_SPI_MASTER);
void * bus = perimanGetPinBus(mosi, ESP32_BUS_TYPE_SPI_MASTER_MOSI);
if(bus != NULL && !perimanSetPinBus(mosi, ESP32_BUS_TYPE_INIT, NULL)){
return false;
}
pinMode(mosi, OUTPUT);
pinMatrixOutAttach(mosi, SPI_MOSI_IDX(spi->num), false, false);
spi->mosi = mosi;
if(!perimanSetPinBus(mosi, ESP32_BUS_TYPE_SPI_MASTER, (void *)(spi->num+1))){
if(!perimanSetPinBus(mosi, ESP32_BUS_TYPE_SPI_MASTER_MOSI, (void *)(spi->num+1))){
spiDetachBus((void *)(spi->num+1));
log_e("Failed to set pin bus to SPI for pin %d", mosi);
return false;
Expand Down Expand Up @@ -300,15 +300,15 @@ bool spiAttachSS(spi_t * spi, uint8_t cs_num, int8_t ss)
if(!spi || ss < 0 || cs_num > 2) {
return false;
}
void * bus = perimanGetPinBus(ss, ESP32_BUS_TYPE_SPI_MASTER);
void * bus = perimanGetPinBus(ss, ESP32_BUS_TYPE_SPI_MASTER_CS);
if(bus != NULL && !perimanSetPinBus(ss, ESP32_BUS_TYPE_INIT, NULL)){
return false;
}
pinMode(ss, OUTPUT);
pinMatrixOutAttach(ss, SPI_SS_IDX(spi->num, cs_num), false, false);
spiEnableSSPins(spi, (1 << cs_num));
spi->ss = ss;
if(!perimanSetPinBus(ss, ESP32_BUS_TYPE_SPI_MASTER, (void *)(spi->num+1))){
if(!perimanSetPinBus(ss, ESP32_BUS_TYPE_SPI_MASTER_CS, (void *)(spi->num+1))){
spiDetachBus((void *)(spi->num+1));
log_e("Failed to set pin bus to SPI for pin %d", ss);
return false;
Expand Down Expand Up @@ -571,7 +571,11 @@ spi_t * spiStartBus(uint8_t spi_num, uint32_t clockDiv, uint8_t dataMode, uint8_
return NULL;
}

perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER, spiDetachBus);
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_SCK, spiDetachBus);
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_MISO, spiDetachBus);
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_MOSI, spiDetachBus);
perimanSetBusDeinit(ESP32_BUS_TYPE_SPI_MASTER_CS, spiDetachBus);

spi_t * spi = &_spi_bus_array[spi_num];

#if !CONFIG_DISABLE_HAL_LOCKS
Expand Down
6 changes: 3 additions & 3 deletions cores/esp32/esp32-hal-tinyusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ static void configure_pins(usb_hal_context_t *usb)
if (!usb->use_external_phy) {
gpio_set_drive_capability(USBPHY_DM_NUM, GPIO_DRIVE_CAP_3);
gpio_set_drive_capability(USBPHY_DP_NUM, GPIO_DRIVE_CAP_3);
if (perimanSetBusDeinit(ESP32_BUS_TYPE_USB, usb_otg_deinit)) {
if (perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DM, usb_otg_deinit) && perimanSetBusDeinit(ESP32_BUS_TYPE_USB_DP, usb_otg_deinit)){
// Bus Pointer is not used anyway - once the USB GPIOs are assigned, they can't be detached
perimanSetPinBus(USBPHY_DM_NUM, ESP32_BUS_TYPE_USB, (void *) usb);
perimanSetPinBus(USBPHY_DP_NUM, ESP32_BUS_TYPE_USB, (void *) usb);
perimanSetPinBus(USBPHY_DM_NUM, ESP32_BUS_TYPE_USB_DM, (void *) usb);
perimanSetPinBus(USBPHY_DP_NUM, ESP32_BUS_TYPE_USB_DP, (void *) usb);
} else {
log_e("USB OTG Pins can't be set into Peripheral Manager.");
}
Expand Down
Loading