First commit XiUOS

This commit is contained in:
xuetest
2021-04-28 17:49:18 +08:00
commit 6001051eb7
1331 changed files with 433955 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
SRC_DIR := third_party_usb
SRC_FILES += dev_usb.c drv_usb.c bus_usb.c
include $(KERNEL_ROOT)/compiler.mk
+125
View File
@@ -0,0 +1,125 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file bus_usb.c
* @brief register usb bus function using bus driver framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <bus_usb.h>
#include <dev_usb.h>
/*Register the USB BUS*/
int UsbBusInit(struct UsbBus *usb_bus, const char *bus_name)
{
NULL_PARAM_CHECK(usb_bus);
NULL_PARAM_CHECK(bus_name);
x_err_t ret = EOK;
if (BUS_INSTALL != usb_bus->bus.bus_state) {
strncpy(usb_bus->bus.bus_name, bus_name, NAME_NUM_MAX);
usb_bus->bus.bus_type = TYPE_USB_BUS;
usb_bus->bus.bus_state = BUS_INSTALL;
usb_bus->bus.private_data = usb_bus->private_data;
ret = BusRegister(&usb_bus->bus);
if (EOK != ret) {
KPrintf("UsbBusInit BusRegister error %u\n", ret);
return ret;
}
} else {
KPrintf("UsbBusInit BusRegister bus has been register state%u\n", usb_bus->bus.bus_state);
}
return ret;
}
/*Register the USB Driver*/
int UsbDriverInit(struct UsbDriver *usb_driver, const char *driver_name)
{
NULL_PARAM_CHECK(usb_driver);
NULL_PARAM_CHECK(driver_name);
x_err_t ret = EOK;
if (DRV_INSTALL != usb_driver->driver.driver_state) {
usb_driver->driver.driver_type = TYPE_USB_DRV;
usb_driver->driver.driver_state = DRV_INSTALL;
strncpy(usb_driver->driver.drv_name, driver_name, NAME_NUM_MAX);
usb_driver->driver.configure = usb_driver->configure;
usb_driver->driver.private_data = usb_driver->private_data;
ret = UsbDriverRegister(&usb_driver->driver);
if (EOK != ret) {
KPrintf("UsbDriverInit DriverRegister error %u\n", ret);
return ret;
}
} else {
KPrintf("UsbDriverInit DriverRegister driver has been register state%u\n", usb_driver->driver.driver_state);
}
return ret;
}
/*Release the USB device*/
int UsbReleaseBus(struct UsbBus *usb_bus)
{
NULL_PARAM_CHECK(usb_bus);
return BusRelease(&usb_bus->bus);
}
/*Register the USB Driver to the USB BUS*/
int UsbDriverAttachToBus(const char *drv_name, const char *bus_name)
{
NULL_PARAM_CHECK(drv_name);
NULL_PARAM_CHECK(bus_name);
x_err_t ret = EOK;
struct Bus *bus;
struct Driver *driver;
bus = BusFind(bus_name);
if (NONE == bus) {
KPrintf("UsbDriverAttachToBus find usb bus error!name %s\n", bus_name);
return ERROR;
}
if (TYPE_USB_BUS == bus->bus_type) {
driver = UsbDriverFind(drv_name, TYPE_USB_DRV);
if (NONE == driver) {
KPrintf("UsbDriverAttachToBus find usb driver error!name %s\n", drv_name);
return ERROR;
}
if (TYPE_USB_DRV == driver->driver_type) {
ret = DriverRegisterToBus(bus, driver);
if (EOK != ret) {
KPrintf("UsbDriverAttachToBus DriverRegisterToBus error %u\n", ret);
return ERROR;
}
}
}
return ret;
}
+118
View File
@@ -0,0 +1,118 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file dev_usb.c
* @brief register usb dev function using bus driver framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <bus_usb.h>
#include <dev_usb.h>
static DoubleLinklistType usbdev_linklist;
/*Create the usb device linklist*/
static void USBDeviceLinkInit()
{
InitDoubleLinkList(&usbdev_linklist);
}
/*Find the register USB device*/
HardwareDevType USBDeviceFind(const char *dev_name, enum DevType dev_type)
{
NULL_PARAM_CHECK(dev_name);
struct HardwareDev *device = NONE;
DoubleLinklistType *node = NONE;
DoubleLinklistType *head = &usbdev_linklist;
for (node = head->node_next; node != head; node = node->node_next) {
device = SYS_DOUBLE_LINKLIST_ENTRY(node, struct HardwareDev, dev_link);
if ((!strcmp(device->dev_name, dev_name)) && (dev_type == device->dev_type)) {
return device;
}
}
KPrintf("USBDeviceFind cannot find the %s device.return NULL\n", dev_name);
return NONE;
}
/*Register the USB device*/
int USBDeviceRegister(struct UsbHardwareDevice *usb_device, void *usb_param, const char *device_name)
{
NULL_PARAM_CHECK(usb_device);
NULL_PARAM_CHECK(device_name);
x_err_t ret = EOK;
static x_bool dev_link_flag = RET_FALSE;
if (dev_link_flag) {
USBDeviceLinkInit();
dev_link_flag = RET_TRUE;
}
if (DEV_INSTALL != usb_device->haldev.dev_state) {
strncpy(usb_device->haldev.dev_name, device_name, NAME_NUM_MAX);
usb_device->haldev.dev_type = TYPE_USB_DEV;
usb_device->haldev.dev_state = DEV_INSTALL;
usb_device->haldev.dev_done = (struct HalDevDone *)usb_device->dev_done;
usb_device->haldev.private_data = usb_param;
DoubleLinkListInsertNodeAfter(&usbdev_linklist, &(usb_device->haldev.dev_link));
} else {
KPrintf("USBDeviceRegister device has been register state%u\n", usb_device->haldev.dev_state);
}
return ret;
}
/*Register the USB Device to the USB BUS*/
int USBDeviceAttachToBus(const char *dev_name, const char *bus_name)
{
NULL_PARAM_CHECK(dev_name);
NULL_PARAM_CHECK(bus_name);
x_err_t ret = EOK;
struct Bus *bus;
struct HardwareDev *device;
bus = BusFind(bus_name);
if (NONE == bus) {
KPrintf("USBDeviceAttachToBus find usb bus error!name %s\n", bus_name);
return ERROR;
}
if (TYPE_USB_BUS == bus->bus_type) {
device = USBDeviceFind(dev_name, TYPE_USB_DEV);
if (NONE == device) {
KPrintf("USBDeviceAttachToBus find usb device error!name %s\n", dev_name);
return ERROR;
}
if (TYPE_USB_DEV == device->dev_type) {
ret = DeviceRegisterToBus(bus, device);
if (EOK != ret) {
KPrintf("usbDeviceAttachToBus DeviceRegisterToBus error %u\n", ret);
return ERROR;
}
}
}
return EOK;
}
+69
View File
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2020 AIIT XUOS Lab
* XiUOS is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* @file drv_usb.c
* @brief register usb drv function using bus driver framework
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-24
*/
#include <bus_usb.h>
#include <dev_usb.h>
static DoubleLinklistType usbdrv_linklist;
/*Create the driver linklist*/
static void UsbDrvLinkInit()
{
InitDoubleLinkList(&usbdrv_linklist);
}
/*Find the regiter driver*/
DriverType UsbDriverFind(const char *drv_name, enum DriverType drv_type)
{
NULL_PARAM_CHECK(drv_name);
struct Driver *driver = NONE;
DoubleLinklistType *node = NONE;
DoubleLinklistType *head = &usbdrv_linklist;
for (node = head->node_next; node != head; node = node->node_next) {
driver = SYS_DOUBLE_LINKLIST_ENTRY(node, struct Driver, driver_link);
if ((!strcmp(driver->drv_name, drv_name)) && (drv_type == driver->driver_type)) {
return driver;
}
}
KPrintf("UsbDriverFind cannot find the %s driver.return NULL\n", drv_name);
return NONE;
}
/*Register the Driver, manage with the double linklist*/
int UsbDriverRegister(struct Driver *driver)
{
NULL_PARAM_CHECK(driver);
x_err_t ret = EOK;
static x_bool driver_link_flag = RET_FALSE;
if (!driver_link_flag) {
UsbDrvLinkInit();
driver_link_flag = RET_TRUE;
}
DoubleLinkListInsertNodeAfter(&usbdrv_linklist, &(driver->driver_link));
return ret;
}
+3
View File
@@ -0,0 +1,3 @@
SRC_DIR := usbhost
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,4 @@
SRC_DIR := core class
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,4 @@
SRC_FILES += mass.c
SRC_FILES += udisk.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,571 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2011-12-12 Yi Qiu first version
*/
/**
* @file mass.c
* @brief support usb storage function
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: mass.c
Description: support usb storage function
Others: take RT-Thread v4.0.2/components/drivers/usb/usbhost/class/mass.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. support usb storage configure, function and struct
2. support usb bus driver framework
*************************************************/
#include <xiuos.h>
#include <usb_host.h>
#include "mass.h"
#ifdef USBH_MSTORAGE
extern x_err_t UdiskRun(struct uhintf* intf);
extern x_err_t UdiskStop(struct uhintf* intf);
static struct UclassDriver StorageDriver;
static x_err_t PipeCheck(struct uhintf* intf, upipe_t pipe)
{
struct uinstance* device;
x_err_t ret;
UstorPointer stor;
int size = 0;
struct UstorageCsw csw;
if(intf == NONE || pipe == NONE)
{
KPrintf("the interface is not available\n");
return -EPIO;
}
device = intf->device;
stor = (UstorPointer)intf->UserData;
if(pipe->status == UPIPE_STATUS_OK) return EOK;
if(pipe->status == UPIPE_STATUS_ERROR)
{
KPrintf("pipe status error\n");
return -EPIO;
}
if(pipe->status == UPIPE_STATUS_STALL)
{
ret = UsbhClearFeature(device, pipe->ep.bEndpointAddress,
USB_FEATURE_ENDPOINT_HALT);
if(ret != EOK) return ret;
}
DelayKTask(50);
KPrintf("pipes1 0x%x, 0x%x\n", stor->pipe_in, stor->pipe_out);
stor->pipe_in->status = UPIPE_STATUS_OK;
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("clean storage in pipe stall\n"));
size = UsbHcdPipeXfer(stor->pipe_in->inst->hcd,
stor->pipe_in, &csw, SIZEOF_CSW, 100);
if(size != SIZEOF_CSW)
{
KPrintf("receive the csw after stall failed\n");
return -EPIO;
}
return -ERROR;
}
static x_err_t UsbBulkOnlyXfer(struct uhintf* intf,
UstorageCbwPointer cmd, uint8* buffer, int timeout)
{
x_size_t size;
x_err_t ret;
upipe_t pipe;
struct UstorageCsw csw;
UstorPointer stor;
NULL_PARAM_CHECK(cmd);
if(intf == NONE)
{
KPrintf("the interface is not available\n");
return -EPIO;
}
stor = (UstorPointer)intf->UserData;
do
{
size = UsbHcdPipeXfer(stor->pipe_out->inst->hcd, stor->pipe_out,
cmd, SIZEOF_CBW, timeout);
if(size != SIZEOF_CBW)
{
KPrintf("CBW size error\n");
return -EPIO;
}
if(cmd->XferLen != 0)
{
pipe = (cmd->dflags == CBWFLAGS_DIR_IN) ? stor->pipe_in :
stor->pipe_out;
size = UsbHcdPipeXfer(pipe->inst->hcd, pipe, (void*)buffer,
cmd->XferLen, timeout);
if(size != cmd->XferLen)
{
KPrintf("request size %d, transfer size %d\n",
cmd->XferLen, size);
break;
}
}
size = UsbHcdPipeXfer(stor->pipe_in->inst->hcd, stor->pipe_in,
&csw, SIZEOF_CSW, timeout);
if(size != SIZEOF_CSW)
{
KPrintf("csw size error\n");
return -EPIO;
}
}while(0);
ret = PipeCheck(intf, stor->pipe_in);
if(ret != EOK)
{
KPrintf("in pipe error\n");
return ret;
}
ret = PipeCheck(intf, stor->pipe_out);
if(ret != EOK)
{
KPrintf("out pipe error\n");
return ret;
}
if(csw.signature != CSW_SIGNATURE || csw.tag != CBW_TAG_VALUE)
{
KPrintf("csw signature error\n");
return -EPIO;
}
if(csw.status != 0)
{
return -ERROR;
}
return EOK;
}
x_err_t UsbhStorageGetMaxLun(struct uhintf* intf, uint8* MaxLun)
{
struct uinstance* device;
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
if(intf == NONE)
{
KPrintf("the interface is not available\n");
return -EPIO;
}
NULL_PARAM_CHECK(intf->device);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("UsbhStorageGetMaxLun\n"));
device = intf->device;
setup.RequestType = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS |
USB_REQ_TYPE_INTERFACE;
setup.bRequest = USBREQ_GET_MAX_LUN;
setup.wValue = intf->IntfDesc->bInterfaceNumber;
setup.wIndex = 0;
setup.wLength = 1;
if(UsbHcdSetupXfer(device->hcd, device->PipeEp0Out, &setup, timeout) != 8)
{
return -EPIO;
}
if(UsbHcdPipeXfer(device->hcd, device->PipeEp0In, MaxLun, 1, timeout) != 1)
{
return -EPIO;
}
if(UsbHcdPipeXfer(device->hcd, device->PipeEp0Out, NONE, 0, timeout) != 0)
{
return -EPIO;
}
return EOK;
}
x_err_t UsbhStorageReset(struct uhintf* intf)
{
struct urequest setup;
struct uinstance* device;
int timeout = USB_TIMEOUT_BASIC;
if(intf == NONE)
{
KPrintf("the interface is not available\n");
return -EPIO;
}
NULL_PARAM_CHECK(intf->device);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("UsbhStorageReset\n"));
device = intf->device;
setup.RequestType = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS |
USB_REQ_TYPE_INTERFACE;
setup.bRequest = USBREQ_MASS_STORAGE_RESET;
setup.wIndex = intf->IntfDesc->bInterfaceNumber;
setup.wLength = 0;
setup.wValue = 0;
if(UsbHcdSetupXfer(device->hcd, device->PipeEp0Out, &setup, timeout) != 8)
{
return -EPIO;
}
if(UsbHcdPipeXfer(device->hcd, device->PipeEp0In, NONE, 0, timeout) != 0)
{
return -EPIO;
}
return EOK;
}
x_err_t UsbhStorageRead10(struct uhintf* intf, uint8 *buffer,
uint32 sector, x_size_t count, int timeout)
{
struct UstorageCbw cmd;
if(intf == NONE)
{
KPrintf("interface is not available\n");
return -EPIO;
}
NULL_PARAM_CHECK(intf->device);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("UsbhStorageRead10\n"));
memset(&cmd, 0, sizeof(struct UstorageCbw));
cmd.signature = CBW_SIGNATURE;
cmd.tag = CBW_TAG_VALUE;
cmd.XferLen = SECTOR_SIZE * count;
cmd.dflags = CBWFLAGS_DIR_IN;
cmd.lun = 0;
cmd.CbLen = 10;
cmd.cb[0] = SCSI_READ_10;
cmd.cb[1] = 0;
cmd.cb[2] = (uint8)(sector >> 24);
cmd.cb[3] = (uint8)(sector >> 16);
cmd.cb[4] = (uint8)(sector >> 8);
cmd.cb[5] = (uint8)sector;
cmd.cb[6] = 0;
cmd.cb[7] = (count & 0xff00) >> 8;
cmd.cb[8] = (uint8) count & 0xff;
return UsbBulkOnlyXfer(intf, &cmd, buffer, timeout);
}
x_err_t UsbhStorageWrite10(struct uhintf* intf, uint8 *buffer,
uint32 sector, x_size_t count, int timeout)
{
struct UstorageCbw cmd;
if(intf == NONE)
{
KPrintf("the interface is not available\n");
return -EPIO;
}
NULL_PARAM_CHECK(intf->device);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("UsbhStorageWrite10\n"));
memset(&cmd, 0, sizeof(struct UstorageCbw));
cmd.signature = CBW_SIGNATURE;
cmd.tag = CBW_TAG_VALUE;
cmd.XferLen = SECTOR_SIZE * count;
cmd.dflags = CBWFLAGS_DIR_OUT;
cmd.lun = 0;
cmd.CbLen = 10;
cmd.cb[0] = SCSI_WRITE_10;
cmd.cb[1] = 0;
cmd.cb[2] = (uint8)(sector >> 24);
cmd.cb[3] = (uint8)(sector >> 16);
cmd.cb[4] = (uint8)(sector >> 8);
cmd.cb[5] = (uint8)sector;
cmd.cb[6] = 0;
cmd.cb[7] = (count & 0xff00) >> 8;
cmd.cb[8] = (uint8) count & 0xff;
return UsbBulkOnlyXfer(intf, &cmd, buffer, timeout);
}
x_err_t UsbhStorageRequestSense(struct uhintf* intf, uint8* buffer)
{
struct UstorageCbw cmd;
int timeout = USB_TIMEOUT_LONG;
if(intf == NONE)
{
KPrintf("the interface is not available\n");
return -EPIO;
}
NULL_PARAM_CHECK(intf->device);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("UsbhStorageRequestSense\n"));
memset(&cmd, 0, sizeof(struct UstorageCbw));
cmd.signature = CBW_SIGNATURE;
cmd.tag = CBW_TAG_VALUE;
cmd.XferLen = 18;
cmd.dflags = CBWFLAGS_DIR_IN;
cmd.lun = 0;
cmd.CbLen = 6;
cmd.cb[0] = SCSI_REQUEST_SENSE;
cmd.cb[4] = 18;
return UsbBulkOnlyXfer(intf, &cmd, buffer, timeout);
}
x_err_t UsbhStorageTestUnitReady(struct uhintf* intf)
{
struct UstorageCbw cmd;
int timeout = USB_TIMEOUT_LONG;
if(intf == NONE)
{
KPrintf("the interface is not available\n");
return -EPIO;
}
NULL_PARAM_CHECK(intf->device);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("UsbhStorageTestUnitReady\n"));
memset(&cmd, 0, sizeof(struct UstorageCbw));
cmd.signature = CBW_SIGNATURE;
cmd.tag = CBW_TAG_VALUE;
cmd.XferLen = 0;
cmd.dflags = CBWFLAGS_DIR_OUT;
cmd.lun = 0;
cmd.CbLen = 12;
cmd.cb[0] = SCSI_TEST_UNIT_READY;
return UsbBulkOnlyXfer(intf, &cmd, NONE, timeout);
}
x_err_t UsbhStorageInquiry(struct uhintf* intf, uint8* buffer)
{
struct UstorageCbw cmd;
int timeout = USB_TIMEOUT_LONG;
if(intf == NONE)
{
KPrintf("the interface is not available\n");
return -EPIO;
}
NULL_PARAM_CHECK(intf->device);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("UsbhStorageInquiry\n"));
memset(&cmd, 0, sizeof(struct UstorageCbw));
cmd.signature = CBW_SIGNATURE;
cmd.tag = CBW_TAG_VALUE;
cmd.XferLen = 36;
cmd.dflags = CBWFLAGS_DIR_IN;
cmd.lun = 0;
cmd.CbLen = 6;
cmd.cb[0] = SCSI_INQUIRY_CMD;
cmd.cb[4] = 36;
return UsbBulkOnlyXfer(intf, &cmd, buffer, timeout);
}
x_err_t UsbhStorageGetCapacity(struct uhintf* intf, uint8* buffer)
{
struct UstorageCbw cmd;
int timeout = USB_TIMEOUT_LONG;
if(intf == NONE)
{
KPrintf("the interface is not available\n");
return -EPIO;
}
NULL_PARAM_CHECK(intf->device);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("UsbhStorageGetCapacity\n"));
memset(&cmd, 0, sizeof(struct UstorageCbw));
cmd.signature = CBW_SIGNATURE;
cmd.tag = CBW_TAG_VALUE;
cmd.XferLen = 8;
cmd.dflags = CBWFLAGS_DIR_IN;
cmd.lun = 0;
cmd.CbLen = 12;
cmd.cb[0] = SCSI_READ_CAPACITY;
return UsbBulkOnlyXfer(intf, &cmd, buffer, timeout);
}
static x_err_t UsbhStorageEnable(void* arg)
{
int i = 0;
x_err_t ret;
UstorPointer stor;
struct uhintf* intf = (struct uhintf*)arg;
if(intf == NONE)
{
KPrintf("the interface is not available\n");
return -EPIO;
}
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("subclass %d, protocal %d\n",
intf->IntfDesc->bInterfaceSubClass,
intf->IntfDesc->bInterfaceProtocol));
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("usbh_storage_run\n"));
stor = x_malloc(sizeof(struct ustor));
NULL_PARAM_CHECK(stor);
memset(stor, 0, sizeof(struct ustor));
intf->UserData = (void*)stor;
for(i=0; i<intf->IntfDesc->bNumEndpoints; i++)
{
UepDescPointer EpDesc;
UsbhGetEndpointDescriptor(intf->IntfDesc, i, &EpDesc);
if(EpDesc == NONE)
{
KPrintf("usb_get_endpoint_descriptor error\n");
return -ERROR;
}
if((EpDesc->bmAttributes & USB_EP_ATTR_TYPE_MASK) != USB_EP_ATTR_BULK)
continue;
if(EpDesc->bEndpointAddress & USB_DIR_IN)
{
stor->pipe_in = UsbInstanceFindPipe(intf->device,EpDesc->bEndpointAddress);
}
else
{
stor->pipe_out = UsbInstanceFindPipe(intf->device,EpDesc->bEndpointAddress);
}
}
if(stor->pipe_in == NONE || stor->pipe_out == NONE)
{
KPrintf("pipe error, unsupported device\n");
return -ERROR;
}
ret = UdiskRun(intf);
if(ret != EOK) return ret;
return EOK;
}
static x_err_t UsbhStorageDisable(void* arg)
{
UstorPointer stor;
struct uhintf* intf = (struct uhintf*)arg;
NULL_PARAM_CHECK(intf);
NULL_PARAM_CHECK(intf->UserData);
NULL_PARAM_CHECK(intf->device );
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("usbh_storage_stop\n"));
stor = (UstorPointer)intf->UserData;
UdiskStop(intf);
if(stor != NONE) x_free(stor);
return EOK;
}
UcdPointer UsbhClassDriverStorage(void)
{
StorageDriver.ClassCode = USB_CLASS_MASS_STORAGE;
StorageDriver.enable = UsbhStorageEnable;
StorageDriver.disable = UsbhStorageDisable;
return &StorageDriver;
}
#endif
@@ -0,0 +1,70 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2011-12-12 Yi Qiu first version
*/
/**
* @file mass.h
* @brief define usb storage function and struct
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: mass.h
Description: define usb storage function and struct
Others: take RT-Thread v4.0.2/components/drivers/usb/usbhost/class/mass.h for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. support define usb storage configure, function and struct
2. support usb bus driver framework
*************************************************/
#ifndef __MASS_H__
#define __MASS_H__
#include <xiuos.h>
#define MAX_PARTITION_COUNT 4
#define SECTOR_SIZE 512
struct UstorData
{
struct uhintf* intf;
int UdiskId;
const char path;
};
struct ustor
{
upipe_t pipe_in;
upipe_t pipe_out;
uint32 capicity[2];
uint8 DevCnt;
};
typedef struct ustor* UstorPointer;
x_err_t UsbhStorageGetMaxLun(struct uhintf* intf, uint8* MaxLun);
x_err_t UsbhStorageReset(struct uhintf* intf);
x_err_t UsbhStorageRead10(struct uhintf* intf, uint8 *buffer,
uint32 sector, x_size_t count, int timeout);
x_err_t UsbhStorageWrite10(struct uhintf* intf, uint8 *buffer,
uint32 sector, x_size_t count, int timeout);
x_err_t UsbhStorageRequestSense(struct uhintf* intf, uint8* buffer);
x_err_t UsbhStorageTestUnitReady(struct uhintf* intf);
x_err_t UsbhStorageInquiry(struct uhintf* intf, uint8* buffer);
x_err_t UsbhStorageGetCapacity(struct uhintf* intf, uint8* buffer);
#endif
@@ -0,0 +1,398 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2011-12-12 Yi Qiu first version
*/
/**
* @file udisk.c
* @brief support usb udisk function , write and read
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: udisk.c
Description: support usb udisk function , write and read
Others: take RT-Thread v4.0.2/components/drivers/usb/usbhost/class/udisk.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. support usb udisk configure, function and struct
2. support usb bus driver framework
*************************************************/
#include <xiuos.h>
#include <usb_host.h>
#include "mass.h"
#if defined(FS_VFS)
#include <iot-vfs.h>
#endif
#ifdef USBH_MSTORAGE
#include <bus.h>
#include <bus_usb.h>
#include <dev_usb.h>
#define UDISK_MAX_COUNT 8
static uint8 UdiskIdset = 0;
static int UdiskGetId(void)
{
int i;
for(i=0; i< UDISK_MAX_COUNT; i++)
{
if((UdiskIdset & (1 << i)) != 0) continue;
else break;
}
if(i == UDISK_MAX_COUNT) CHECK(0);
UdiskIdset |= (1 << i);
return i;
}
static void UdiskFreeId(int id)
{
CHECK(id < UDISK_MAX_COUNT);
UdiskIdset &= ~(1 << id);
}
static x_size_t UdiskRead_new(struct UstorData* data, x_OffPos pos, void* buffer,
x_size_t size)
{
x_err_t ret;
struct uhintf* intf;
int timeout = USB_TIMEOUT_LONG;
NULL_PARAM_CHECK(buffer);
if(size > 4096) timeout *= 2;
intf = data->intf;
ret = UsbhStorageRead10(intf, (uint8*)buffer, pos, size, timeout);
if (ret != EOK)
{
KPrintf("usb mass_storage read failed\n");
return 0;
}
return size;
}
static x_size_t UdiskWrite_new (struct UstorData* data, x_OffPos pos, const void* buffer,
x_size_t size)
{
x_err_t ret;
struct uhintf* intf;
int timeout = USB_TIMEOUT_LONG;
NULL_PARAM_CHECK(buffer);
if(size * SECTOR_SIZE > 4096) timeout *= 2;
intf = data->intf;
ret = UsbhStorageWrite10(intf, (uint8*)buffer, pos, size, timeout);
if (ret != EOK)
{
KPrintf("usb mass_storage write %d sector failed\n", size);
return 0;
}
return size;
}
uint32 UdiskRead_new_api(void *dev, struct BusBlockReadParam *read_param)
{
struct UsbHardwareDevice* usb_dev = (struct UsbHardwareDevice*)dev;
return UdiskRead_new(usb_dev->private_data, read_param->pos, read_param->buffer, read_param->size);
}
uint32 UdiskWirte_new_api(void *dev, struct BusBlockWriteParam *write_param)
{
struct UsbHardwareDevice* usb_dev = (struct UsbHardwareDevice*)dev;
return UdiskWrite_new(usb_dev->private_data, write_param->pos, write_param->buffer, write_param->size);
}
x_err_t UdiskRun(struct uhintf* intf)
{
int i = 0;
x_err_t ret;
char dname[8];
char sname[8];
uint8 MaxLun, *sector, sense[18], inquiry[36];
UstorPointer stor;
NULL_PARAM_CHECK(intf );
ret = UsbhStorageReset(intf);
if(ret != EOK) return ret;
stor = (UstorPointer)intf->UserData;
ret = UsbhStorageGetMaxLun(intf, &MaxLun);
if(ret != EOK)
UsbhClearFeature(intf->device, 0, USB_FEATURE_ENDPOINT_HALT);
if(stor->pipe_in->status == UPIPE_STATUS_STALL)
{
ret = UsbhClearFeature(intf->device,
stor->pipe_in->ep.bEndpointAddress, USB_FEATURE_ENDPOINT_HALT);
if(ret != EOK) return ret;
}
if(stor->pipe_out->status == UPIPE_STATUS_STALL)
{
ret = UsbhClearFeature(intf->device,
stor->pipe_out->ep.bEndpointAddress, USB_FEATURE_ENDPOINT_HALT);
if(ret != EOK) return ret;
}
while((ret = UsbhStorageInquiry(intf, inquiry)) != EOK)
{
if(ret == -EPIO) return ret;
DelayKTask(5);
if(i++ < 10) continue;
KPrintf("UsbhStorageInquiry error\n");
return -ERROR;
}
i = 0;
while((ret = UsbhStorageTestUnitReady(intf)) != EOK)
{
if(ret == -EPIO) return ret;
ret = UsbhStorageRequestSense(intf, sense);
if(ret == -EPIO) return ret;
DelayKTask(10);
if(i++ < 10) continue;
KPrintf("UsbhStorageTestUnitReady error\n");
return -ERROR;
}
i = 0;
memset(stor->capicity, 0, sizeof(stor->capicity));
while((ret = UsbhStorageGetCapacity(intf,
(uint8*)stor->capicity)) != EOK)
{
if(ret == -EPIO) return ret;
DelayKTask(50);
if(i++ < 10) continue;
stor->capicity[0] = 2880;
stor->capicity[1] = 0x200;
KPrintf("UsbhStorageGetCapacity error\n");
break;
}
stor->capicity[0] = uswap_32(stor->capicity[0]);
stor->capicity[1] = uswap_32(stor->capicity[1]);
stor->capicity[0] += 1;
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("capicity %d, block size %d\n",
stor->capicity[0], stor->capicity[1]));
sector = (uint8*) x_malloc (SECTOR_SIZE);
if (sector == NONE)
{
KPrintf("allocate partition sector buffer failed\n");
return -ERROR;
}
memset(sector, 0, SECTOR_SIZE);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("read partition table\n"));
ret = UsbhStorageRead10(intf, sector, 0, 1, USB_TIMEOUT_LONG);
if(ret != EOK)
{
KPrintf("read parition table error\n");
x_free(sector);
return -ERROR;
}
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("finished reading partition\n"));
struct UstorData* data = x_malloc(sizeof(struct UstorData));
memset(data, 0, sizeof(struct UstorData));
data->UdiskId = UdiskGetId();
data->intf = intf;
snprintf(dname, sizeof(dname), "udisk%d", data->UdiskId);
struct Bus* usb_bus = BusFind(UDISK_USB_BUS_NAME);
struct UsbHardwareDevice* usb_dev = (struct UsbHardwareDevice*)BusFindDevice(usb_bus, UDISK_USB_DEVICE_NAME);
if (usb_dev)
{
KPrintf("udisk.c find usb dev seccess\n");
usb_dev->private_data = (void*)data;
}
else
{
KPrintf("udisk.c find usb dev fail \n");
}
data->intf = intf;
NULL_PARAM_CHECK(data);
NULL_PARAM_CHECK(intf );
CHECK(data->intf == intf);
stor->DevCnt++;
if (MountFilesystem(UDISK_USB_BUS_NAME, UDISK_USB_DEVICE_NAME,USB_DRIVER_NAME, FSTYPE_FATFS, UDISK_MOUNTPOINT) == 0)
KPrintf("Mount FAT on Udisk successful.\n");
else
KPrintf("Mount FAT on Udisk failed.\n");
// for(i=0; i<MAX_PARTITION_COUNT; i++)
// {
// /* get the first partition */
// ret = dfs_filesystem_get_partition(&part[i], sector, i);
// if (ret == EOK)
// {
// struct ustor_data* data = x_malloc(sizeof(struct ustor_data));
// memset(data, 0, sizeof(struct ustor_data));
// data->intf = intf;
// data->udisk_id = udisk_get_id();
// snprintf(dname, 6, "ud%d-%d", data->udisk_id, i);
// snprintf(sname, 8, "sem_ud%d", i);
// data->part.lock = KSemaphoreCreate( 1);
// /* register sdcard device */
// stor->dev[i].type = Dev_TYPE_Block;
// stor->dev[i].init = udisk_init;
// stor->dev[i].read = udisk_read;
// stor->dev[i].write = udisk_write;
// stor->dev[i].control = udisk_control;
// stor->dev[i].UserData = (void*)data;
// DeviceRegister(&stor->dev[i], dname, SIGN_OPER_RDWR |
// SIGN_OPER_REMOVABLE |SIGN_OPER_STANDALONE);
// stor->dev_cnt++;
// if (dfs_mount(stor->dev[i].parent.name, UDISK_MOUNTPOINT, "elm",
// 0, 0) == 0)
// {
// SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("udisk part %d mount successfully\n", i));
// }
// else
// {
// SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("udisk part %d mount failed\n", i));
// }
// }
// else
// {
// if(i == 0)
// {
// struct ustor_data* data = x_malloc(sizeof(struct ustor_data));
// memset(data, 0, sizeof(struct ustor_data));
// data->udisk_id = udisk_get_id();
// /* there is no partition table */
// data->part.offset = 0;
// data->part.size = 0;
// data->intf = intf;
// data->part.lock = KSemaphoreCreate( 1);
// snprintf(dname, 7, "udisk%d", data->udisk_id);
// /* register sdcard device */
// stor->dev[0].type = Dev_TYPE_Block;
// stor->dev[0].init = udisk_init;
// stor->dev[0].read = udisk_read;
// stor->dev[0].write = udisk_write;
// stor->dev[0].control = udisk_control;
// stor->dev[0].UserData = (void*)data;
// DeviceRegister(&stor->dev[0], dname,
// SIGN_OPER_RDWR |SIGN_OPER_REMOVABLE
// |SIGN_OPER_STANDALONE);
// stor->dev_cnt++;
// if (dfs_mount(stor->dev[0].parent.name, UDISK_MOUNTPOINT,
// "elm", 0, 0) == 0)
// {
// KPrintf("Mount FAT on Udisk successful.\n");
// }
// else
// {
// KPrintf("Mount FAT on Udisk failed.\n");
// }
// }
// break;
// }
// }
x_free(sector);
return EOK;
}
x_err_t UdiskStop(struct uhintf* intf)
{
int i;
UstorPointer stor;
NULL_PARAM_CHECK(intf);
NULL_PARAM_CHECK(intf->device);
stor = (UstorPointer)intf->UserData;
NULL_PARAM_CHECK(stor);
for(i=0; i<stor->DevCnt; i++)
{
UnmountFileSystem(UDISK_MOUNTPOINT);
}
return EOK;
}
#endif
@@ -0,0 +1,5 @@
SRC_FILES +=core.c driver.c usbhost.c hub.c
include $(KERNEL_ROOT)/compiler.mk
@@ -0,0 +1,609 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2011-03-12 Yi Qiu first version
*/
/**
* @file core.c
* @brief support usb host function and configure
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: core.c
Description: support usb host function and configure
Others: take RT-Thread v4.0.2/components/drivers/usb/usbhost/core/usbhost_core.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. support usb host configure, function and struct
2. support usb bus driver framework
*************************************************/
#include <xiuos.h>
#include <usb_host.h>
static struct uinstance dev[USB_MAX_DEVICE];
/**
* Allocate a usb host instance
*
* @param uhcd pointer to a uhcd object
*
* @return pointer to a uinstance object (NULL on failure)
*/
UinstPointer UsbhAllocInstance(UhcdPointer uhcd)
{
int i;
x_base lock;
for(i=0; i<USB_MAX_DEVICE; i++)
{
lock = CriticalAreaLock();
if(dev[i].status != DEV_STATUS_IDLE) continue;
memset(&dev[i], 0, sizeof(struct uinstance));
dev[i].status = DEV_STATUS_BUSY;
dev[i].index = i + 1;
dev[i].address = 0;
dev[i].MaxPacketSize = 0x8;
InitDoubleLinkList(&dev[i].pipe);
dev[i].hcd = uhcd;
CriticalAreaUnLock(lock);
return &dev[i];
}
return NONE;
}
static struct UendpointDescriptor Ep0OutDesc =
{
USB_DESC_LENGTH_ENDPOINT,
USB_DESC_TYPE_ENDPOINT,
0x00 | USB_DIR_OUT,
USB_EP_ATTR_CONTROL,
0x00,
0x00,
};
static struct UendpointDescriptor Ep0InDesc =
{
USB_DESC_LENGTH_ENDPOINT,
USB_DESC_TYPE_ENDPOINT,
0x00 | USB_DIR_IN,
USB_EP_ATTR_CONTROL,
0x00,
0x00,
};
/**
* Enumerate and invoke class driver when a usb device is connected
*
* @param device pointer to a uinstance object
*/
x_err_t UsbhAttatchInstance(UinstPointer device)
{
int i = 0;
x_err_t ret = EOK;
struct UconfigDescriptor CfgDesc;
UdevDescPointer DevDesc;
UintfDescPointer IntfDesc;
UepDescPointer EpDesc;
uint8 EpIndex;
upipe_t pipe;
UcdPointer drv;
NULL_PARAM_CHECK(device);
memset(&CfgDesc, 0, sizeof(struct UconfigDescriptor));
DevDesc = &device->DevDesc;
Ep0OutDesc.wMaxPacketSize = 8;
Ep0InDesc.wMaxPacketSize = 8;
UsbHcdAllocPipe(device->hcd, &device->PipeEp0Out, device, &Ep0OutDesc);
UsbHcdAllocPipe(device->hcd, &device->PipeEp0In, device, &Ep0InDesc);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("start enumnation\n"));
ret = UsbhGetDescriptor(device, USB_DESC_TYPE_DEVICE, (void*)DevDesc, 8);
if(ret != EOK)
{
KPrintf("get device descriptor head failed\n");
return ret;
}
UsbhHubResetPort(device->parent_hub, device->port);
DelayKTask(2);
UsbhHubClearPortFeature(device->parent_hub, i + 1, PORT_FEAT_C_CONNECTION);
ret = UsbhSetAddress(device);
if(ret != EOK)
{
KPrintf("set device address failed\n");
return ret;
}
UsbHcdFreePipe(device->hcd,device->PipeEp0Out);
UsbHcdFreePipe(device->hcd,device->PipeEp0In);
Ep0OutDesc.wMaxPacketSize = device->DevDesc.bMaxPacketSize0;
Ep0InDesc.wMaxPacketSize = device->DevDesc.bMaxPacketSize0;
UsbHcdAllocPipe(device->hcd, &device->PipeEp0Out, device, &Ep0OutDesc);
UsbHcdAllocPipe(device->hcd, &device->PipeEp0In, device, &Ep0InDesc);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("get device descriptor length %d\n",
DevDesc->bLength));
ret = UsbhGetDescriptor(device, USB_DESC_TYPE_DEVICE, (void*)DevDesc, DevDesc->bLength);
if(ret != EOK)
{
KPrintf("get full device descriptor failed\n");
return ret;
}
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("Vendor ID 0x%x\n", DevDesc->idVendor));
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("Product ID 0x%x\n", DevDesc->idProduct));
ret = UsbhGetDescriptor(device, USB_DESC_TYPE_CONFIGURATION, &CfgDesc, 18);
if(ret != EOK)
{
KPrintf("get configuration descriptor head failed\n");
return ret;
}
device->CfgDesc = (UcfgDescPointer)x_malloc(CfgDesc.wTotalLength);
memset(device->CfgDesc, 0, CfgDesc.wTotalLength);
ret = UsbhGetDescriptor(device, USB_DESC_TYPE_CONFIGURATION,
device->CfgDesc, CfgDesc.wTotalLength);
if(ret != EOK)
{
KPrintf("get full configuration descriptor failed\n");
return ret;
}
ret = UsbhSetConfigure(device, 1);
if(ret != EOK)
{
return ret;
}
for(i=0; i<device->CfgDesc->bNumInterfaces; i++)
{
ret = UsbhGetInterfaceDescriptor(device->CfgDesc, i, &IntfDesc);
if(ret != EOK)
{
KPrintf("usb_get_interface_descriptor error\n");
return -ERROR;
}
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("interface class 0x%x, subclass 0x%x\n",
IntfDesc->bInterfaceClass,
IntfDesc->bInterfaceSubClass));
for(EpIndex = 0; EpIndex < IntfDesc->bNumEndpoints; EpIndex++)
{
UsbhGetEndpointDescriptor(IntfDesc, EpIndex, &EpDesc);
if(EpDesc != NONE)
{
if(UsbHcdAllocPipe(device->hcd, &pipe, device, EpDesc) != EOK)
{
KPrintf("alloc pipe failed\n");
return ERROR;
}
usb_instance_add_pipe(device,pipe);
}
else
{
KPrintf("get endpoint desc failed\n");
return ERROR;
}
}
drv = UsbhClassDriverFind(IntfDesc->bInterfaceClass,
IntfDesc->bInterfaceSubClass);
if(drv != NONE)
{
device->intf[i] = (struct uhintf*)x_malloc(sizeof(struct uhintf));
device->intf[i]->drv = drv;
device->intf[i]->device = device;
device->intf[i]->IntfDesc = IntfDesc;
device->intf[i]->UserData = NONE;
ret = UsbhClassDriverEnable(drv, (void*)device->intf[i]);
if(ret != EOK)
{
KPrintf("interface %d run class driver error\n", i);
}
}
else
{
KPrintf("find usb device driver failed\n");
continue;
}
}
return EOK;
}
/**
* Detach a connected device
*
* @param device pointer to a uinstance object
*
* @return 0 on success, error code on failure
*/
x_err_t UsbhDetachInstance(UinstPointer device)
{
int i = 0;
DoubleLinklistType * l;
if(device == NONE)
{
KPrintf("no usb instance to detach\n");
return -ERROR;
}
if (device->CfgDesc) {
for (i = 0; i < device->CfgDesc->bNumInterfaces; i++)
{
if (device->intf[i] == NONE) continue;
if (device->intf[i]->drv == NONE) continue;
CHECK(device->intf[i]->device == device);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("free interface instance %d\n", i));
UsbhClassDriverDisable(device->intf[i]->drv, (void*)device->intf[i]);
x_free(device->intf[i]);
}
x_free(device->CfgDesc);
}
UsbHcdFreePipe(device->hcd,device->PipeEp0Out);
UsbHcdFreePipe(device->hcd,device->PipeEp0In);
while(device->pipe.node_next!= &device->pipe)
{
l = device->pipe.node_next;
DoubleLinkListRmNode(l);
UsbHcdFreePipe(device->hcd,SYS_DOUBLE_LINKLIST_ENTRY(l,struct upipe,list));
}
memset(device, 0, sizeof(struct uinstance));
return EOK;
}
/**
* Get device descriptor of a connected device
*
* @param device pointer to a uinstance object
* @param type device type
* @param buffer buffer to store the descriptor
*
* @return 0 on success, error code on failure
*/
x_err_t UsbhGetDescriptor(UinstPointer device, uint8 type, void* buffer,
int nbytes)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
NULL_PARAM_CHECK(device);
setup.RequestType = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_STANDARD |
USB_REQ_TYPE_DEVICE;
setup.bRequest = USB_REQ_GET_DESCRIPTOR;
setup.wIndex = 0;
setup.wLength = nbytes;
setup.wValue = type << 8;
if(UsbHcdSetupXfer(device->hcd, device->PipeEp0Out, &setup, timeout) == 8)
{
if(UsbHcdPipeXfer(device->hcd, device->PipeEp0In, buffer, nbytes, timeout) == nbytes)
{
if(UsbHcdPipeXfer(device->hcd, device->PipeEp0Out, NONE, 0, timeout) == 0)
{
return EOK;
}
}
}
return ERROR;
}
/**
* Set address of a connected device
*
* @param device pointer to a uinstance object
*
* @return 0 on success, error code on failure
*/
x_err_t UsbhSetAddress(UinstPointer device)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
NULL_PARAM_CHECK(device);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("usb_set_address\n"));
setup.RequestType = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
USB_REQ_TYPE_DEVICE;
setup.bRequest = USB_REQ_SET_ADDRESS;
setup.wIndex = 0;
setup.wLength = 0;
setup.wValue = device->index;
if(UsbHcdSetupXfer(device->hcd, device->PipeEp0Out, &setup, timeout) != 8)
{
return ERROR;
}
if(UsbHcdPipeXfer(device->hcd, device->PipeEp0In, NONE, 0, timeout) == 0)
{
device->address = device->index;
}
return EOK;
}
/**
* Set configuration of a connected device
*
* @param device pointer to a uinstance object
* @param config value of configuration
*
* @return 0 on success, error code on failure
*/
x_err_t UsbhSetConfigure(UinstPointer device, int config)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
NULL_PARAM_CHECK(device);
setup.RequestType = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
USB_REQ_TYPE_DEVICE;
setup.bRequest = USB_REQ_SET_CONFIGURATION;
setup.wIndex = 0;
setup.wLength = 0;
setup.wValue = config;
if(UsbHcdSetupXfer(device->hcd, device->PipeEp0Out, &setup, timeout) != 8)
{
return ERROR;
}
if(UsbHcdPipeXfer(device->hcd, device->PipeEp0In, NONE, 0, timeout) != 0)
{
return ERROR;
}
return EOK;
}
/**
* Set interface of a connected device
*
* @param device pointer to a uinstance object
* @param intf interface number
*
* @return 0 on success, error code on failure
*/
x_err_t UsbhSetInterface(UinstPointer device, int intf)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
NULL_PARAM_CHECK(device);
setup.RequestType = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
USB_REQ_TYPE_INTERFACE;
setup.bRequest = USB_REQ_SET_INTERFACE;
setup.wIndex = 0;
setup.wLength = 0;
setup.wValue = intf;
if(UsbHcdSetupXfer(device->hcd, device->PipeEp0Out, &setup, timeout) != 8)
{
return ERROR;
}
return EOK;
}
/**
* Clear feature of a given endpoint
*
* @param device pointer to a uinstance object
* @param endpoint endpoint number
* @param feature feature number
*
* @return 0 on success, error code on failure
*/
x_err_t UsbhClearFeature(UinstPointer device, int endpoint, int feature)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
NULL_PARAM_CHECK(device);
setup.RequestType = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_STANDARD |
USB_REQ_TYPE_ENDPOINT;
setup.bRequest = USB_REQ_CLEAR_FEATURE;
setup.wIndex = endpoint;
setup.wLength = 0;
setup.wValue = feature;
if(UsbHcdSetupXfer(device->hcd, device->PipeEp0Out, &setup, timeout) != 8)
{
return ERROR;
}
return EOK;
}
/**
* Get interface descriptor of a connected device
*
* @param CfgDesc pointer to a UconfigDescriptor object
* @param num interface number
* @param IntfDesc pointer to a UinterfaceDescriptor object
*
* @return 0 on success, error code on failure
*/
x_err_t UsbhGetInterfaceDescriptor(UcfgDescPointer CfgDesc, int num,
UintfDescPointer* IntfDesc)
{
uint64 ptr, depth = 0;
UdescPointer desc;
NULL_PARAM_CHECK(CfgDesc);
ptr = (uint64)CfgDesc + CfgDesc->bLength;
while(ptr < (uint64)CfgDesc + CfgDesc->wTotalLength)
{
if(depth++ > 0x20)
{
*IntfDesc = NONE;
return -EPIO;
}
desc = (UdescPointer)ptr;
if(desc->type == USB_DESC_TYPE_INTERFACE)
{
if(((UintfDescPointer)desc)->bInterfaceNumber == num)
{
*IntfDesc = (UintfDescPointer)desc;
SYS_KDEBUG_LOG(SYS_DEBUG_USB,
("usb_get_interface_descriptor: %d\n", num));
return EOK;
}
}
ptr = (uint64)desc + desc->bLength;
}
KPrintf("usb_get_interface_descriptor %d failed\n", num);
return -EPIO;
}
/**
* Get descriptor of an interface endpoint
*
* @param IntfDesc pointer to an UinterfaceDescriptor object
* @param num endpoint number
* @param EpDesc pointer to an UendpointDescriptor object pointer
*
* @return 0 on success, error code on failure
*/
x_err_t UsbhGetEndpointDescriptor(UintfDescPointer IntfDesc, int num,
UepDescPointer* EpDesc)
{
int count = 0, depth = 0;
uint64 ptr;
UdescPointer desc;
NULL_PARAM_CHECK(IntfDesc);
CHECK(num < IntfDesc->bNumEndpoints);
*EpDesc = NONE;
ptr = (uint64)IntfDesc + IntfDesc->bLength;
while(count < IntfDesc->bNumEndpoints)
{
if(depth++ > 0x20)
{
*EpDesc = NONE;
return -EPIO;
}
desc = (UdescPointer)ptr;
if(desc->type == USB_DESC_TYPE_ENDPOINT)
{
if(num == count)
{
*EpDesc = (UepDescPointer)desc;
SYS_KDEBUG_LOG(SYS_DEBUG_USB,
("usb_get_endpoint_descriptor: %d\n", num));
return EOK;
}
else count++;
}
ptr = (uint64)desc + desc->bLength;
}
KPrintf("usb_get_endpoint_descriptor %d failed\n", num);
return -EPIO;
}
/**
* Transfer data on a specified endpoint (pipe)
*
* @param hcd pointer to a uhcd object
* @param pipe pointer to a upipe object
* @param buffer buffer to store data to be sent/received
* @param nbytes number of bytes to be sent/received
* @param timeout maximum timeout
*
* @return number of bytes sent/received
*/
int UsbHcdPipeXfer(UhcdPointer hcd, upipe_t pipe, void* buffer, int nbytes, int timeout)
{
x_size_t RemainSize;
x_size_t SendSize;
RemainSize = nbytes;
uint8 * pbuffer = (uint8 *)buffer;
do
{
SYS_KDEBUG_LOG(SYS_DEBUG_USB,("pipe transform remain size,: %d\n", RemainSize));
SendSize = (RemainSize > pipe->ep.wMaxPacketSize) ? pipe->ep.wMaxPacketSize : RemainSize;
if(hcd->ops->pipe_xfer(pipe, USBH_PID_DATA, pbuffer, SendSize, timeout) == SendSize)
{
RemainSize -= SendSize;
pbuffer += SendSize;
}
else
{
return 0;
}
}while(RemainSize > 0);
return nbytes;
}
@@ -0,0 +1,118 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2011-03-12 Yi Qiu first version
*/
/**
* @file driver.c
* @brief support usb host driver function and register configure
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: driver.c
Description: support usb host driver function , init and register
Others: take RT-Thread v4.0.2/components/drivers/usb/usbhost/core/driver.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. support usb host driver configure, function and struct
2. support usb bus driver framework
*************************************************/
#include <xiuos.h>
#include <xs_klist.h>
#include <usb_host.h>
static DoubleLinklistType DriverList;
x_err_t UsbhClassDriverInit(void)
{
InitDoubleLinkList(&DriverList);
return EOK;
}
x_err_t UsbhClassDriverRegister(UcdPointer drv)
{
if (drv == NONE) return -ERROR;
DoubleLinkListInsertNodeAfter(&DriverList, &(drv->list));
return EOK;
}
x_err_t UsbhClassDriverUnregister(UcdPointer drv)
{
NULL_PARAM_CHECK(drv);
DoubleLinkListRmNode(&(drv->list));
return EOK;
}
x_err_t UsbhClassDriverEnable(UcdPointer drv, void* args)
{
NULL_PARAM_CHECK(drv);
if(drv->enable != NONE)
drv->enable(args);
return EOK;
}
x_err_t UsbhClassDriverDisable(UcdPointer drv, void* args)
{
NULL_PARAM_CHECK(drv);
if(drv->disable != NONE)
drv->disable(args);
return EOK;
}
UcdPointer UsbhClassDriverFind(int ClassCode, int subclass_code)
{
struct SysDoubleLinklistNode *node;
x_base lock;
if (GetKTaskDescriptor() != NONE)
lock = CriticalAreaLock();
for (node = DriverList.node_next; node != &DriverList; node = node->node_next)
{
UcdPointer drv =
(UcdPointer)SYS_DOUBLE_LINKLIST_ENTRY(node, struct UclassDriver, list);
if (drv->ClassCode == ClassCode)
{
if (GetKTaskDescriptor() != NONE)
CriticalAreaUnLock(lock);
return drv;
}
}
if (GetKTaskDescriptor() != NONE)
CriticalAreaUnLock(lock);
return NONE;
}
@@ -0,0 +1,631 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2011-12-12 Yi Qiu first version
*/
/**
* @file hub.c
* @brief support usb hub driver function and configure
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: hub.c
Description: support usb hub driver function , init and irq configure
Others: take RT-Thread v4.0.2/components/drivers/usb/usbhost/core/hub.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. support usb hub driver configure, function and struct
2. support usb bus driver framework
*************************************************/
#include <xiuos.h>
#include <usb_host.h>
#define USB_THREAD_STACK_SIZE 4096
static int32 UsbMq;
static struct UclassDriver HubDriver;
static struct uhub RootHub;
static x_err_t RootHubCtrl(struct uhcd *hcd, uint16 port, uint8 cmd, void *args)
{
switch(cmd)
{
case RH_GET_PORT_STATUS:
(*(uint32 *)args) = hcd->roothub->PortStatus[port-1];
break;
case RH_SET_PORT_STATUS:
hcd->roothub->PortStatus[port-1] = (*(uint32 *)args);
break;
case RH_CLEAR_PORT_FEATURE:
switch(((uint64)args))
{
case PORT_FEAT_C_CONNECTION:
hcd->roothub->PortStatus[port-1] &= ~PORT_CCSC;
break;
case PORT_FEAT_C_ENABLE:
hcd->roothub->PortStatus[port-1] &= ~PORT_PESC;
break;
case PORT_FEAT_C_SUSPEND:
hcd->roothub->PortStatus[port-1] &= ~PORT_PSSC;
break;
case PORT_FEAT_C_OVER_CURRENT:
hcd->roothub->PortStatus[port-1] &= ~PORT_POCIC;
break;
case PORT_FEAT_C_RESET:
hcd->roothub->PortStatus[port-1] &= ~PORT_PRSC;
break;
}
break;
case RH_SET_PORT_FEATURE:
switch((uint64)args)
{
case PORT_FEAT_CONNECTION:
hcd->roothub->PortStatus[port-1] |= PORT_CCSC;
break;
case PORT_FEAT_ENABLE:
hcd->roothub->PortStatus[port-1] |= PORT_PESC;
break;
case PORT_FEAT_SUSPEND:
hcd->roothub->PortStatus[port-1] |= PORT_PSSC;
break;
case PORT_FEAT_OVER_CURRENT:
hcd->roothub->PortStatus[port-1] |= PORT_POCIC;
break;
case PORT_FEAT_RESET:
hcd->ops->reset_port(port);
break;
case PORT_FEAT_POWER:
break;
case PORT_FEAT_LOWSPEED:
break;
case PORT_FEAT_HIGHSPEED:
break;
}
break;
default:
return ERROR;
}
return EOK;
}
void UsbhRootHubConnectHandler(struct uhcd *hcd, uint8 port, x_bool isHS)
{
struct UhostMsg msg;
msg.type = USB_MSG_CONNECT_CHANGE;
msg.content.hub = hcd->roothub;
hcd->roothub->PortStatus[port - 1] |= PORT_CCS | PORT_CCSC;
if(isHS)
{
hcd->roothub->PortStatus[port - 1] &= ~PORT_LSDA;
}
else
{
hcd->roothub->PortStatus[port - 1] |= PORT_LSDA;
}
UsbhEventSignal(&msg);
}
void UsbhRootHubDisconnectHandler(struct uhcd *hcd, uint8 port)
{
struct UhostMsg msg;
msg.type = USB_MSG_CONNECT_CHANGE;
msg.content.hub = hcd->roothub;
hcd->roothub->PortStatus[port - 1] |= PORT_CCSC;
hcd->roothub->PortStatus[port - 1] &= ~PORT_CCS;
UsbhEventSignal(&msg);
}
x_err_t UsbhHubGetDescriptor(struct uinstance* device, uint8 *buffer, x_size_t nbytes)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
NULL_PARAM_CHECK(device);
setup.RequestType = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_DEVICE;
setup.bRequest = USB_REQ_GET_DESCRIPTOR;
setup.wIndex = 0;
setup.wLength = nbytes;
setup.wValue = USB_DESC_TYPE_HUB << 8;
if(UsbHcdSetupXfer(device->hcd, device->PipeEp0Out, &setup, timeout) == 8)
{
if(UsbHcdPipeXfer(device->hcd, device->PipeEp0In, buffer, nbytes, timeout) == nbytes)
{
return EOK;
}
}
return -RET_FALSE;
}
x_err_t UsbhHubGetStatus(struct uinstance* device, uint32* buffer)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
NULL_PARAM_CHECK(device);
setup.RequestType = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_DEVICE;
setup.bRequest = USB_REQ_GET_STATUS;
setup.wIndex = 0;
setup.wLength = 4;
setup.wValue = 0;
if(UsbHcdSetupXfer(device->hcd, device->PipeEp0Out, &setup, timeout) == 8)
{
if(UsbHcdPipeXfer(device->hcd, device->PipeEp0In, buffer, 4, timeout) == 4)
{
return EOK;
}
}
return -RET_FALSE;
}
x_err_t UsbhHubGetPortStatus(UhubPointer hub, uint16 port, uint32* buffer)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
NULL_PARAM_CHECK(hub);
if(hub->IsRoothub)
{
RootHubCtrl(hub->hcd, port, RH_GET_PORT_STATUS,
(void*)buffer);
return EOK;
}
setup.RequestType = USB_REQ_TYPE_DIR_IN | USB_REQ_TYPE_CLASS | USB_REQ_TYPE_OTHER;
setup.bRequest = USB_REQ_GET_STATUS;
setup.wIndex = port;
setup.wLength = 4;
setup.wValue = 0;
if(UsbHcdSetupXfer(hub->hcd, hub->self->PipeEp0Out, &setup, timeout) == 8)
{
if(UsbHcdPipeXfer(hub->hcd, hub->self->PipeEp0In, buffer, 4, timeout) == 4)
{
return EOK;
}
}
return -RET_FALSE;
}
x_err_t UsbhHubClearPortFeature(UhubPointer hub, uint16 port, uint16 feature)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
NULL_PARAM_CHECK(hub);
if(hub->IsRoothub)
{
RootHubCtrl(hub->hcd, port, RH_CLEAR_PORT_FEATURE,
(void*)(uint64)feature);
return EOK;
}
setup.RequestType = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS |
USB_REQ_TYPE_OTHER;
setup.bRequest = USB_REQ_CLEAR_FEATURE;
setup.wIndex = port;
setup.wLength = 0;
setup.wValue = feature;
if(UsbHcdSetupXfer(hub->hcd, hub->self->PipeEp0Out, &setup, timeout) == 8)
{
return EOK;
}
return -RET_FALSE;
}
x_err_t UsbhHubSetPortFeature(UhubPointer hub, uint16 port,
uint16 feature)
{
struct urequest setup;
int timeout = USB_TIMEOUT_BASIC;
NULL_PARAM_CHECK(hub);
if(hub->IsRoothub)
{
RootHubCtrl(hub->hcd, port, RH_SET_PORT_FEATURE,
(void*)(uint64)feature);
return EOK;
}
setup.RequestType = USB_REQ_TYPE_DIR_OUT | USB_REQ_TYPE_CLASS |
USB_REQ_TYPE_OTHER;
setup.bRequest = USB_REQ_SET_FEATURE;
setup.wIndex = port;
setup.wLength = 0;
setup.wValue = feature;
if(UsbHcdSetupXfer(hub->hcd, hub->self->PipeEp0Out, &setup, timeout) == 8)
{
return EOK;
}
else return -RET_FALSE;
}
x_err_t UsbhHubResetPort(UhubPointer hub, uint16 port)
{
x_err_t ret;
uint32 pstatus;
NULL_PARAM_CHECK(hub);
DelayKTask(50);
ret = UsbhHubSetPortFeature(hub, port, PORT_FEAT_RESET);
if(ret != EOK) return ret;
while(RET_TRUE)
{
ret = UsbhHubGetPortStatus(hub, port, &pstatus);
if(!(pstatus & PORT_PRS)) break;
}
ret = UsbhHubClearPortFeature(hub, port, PORT_FEAT_C_RESET);
if(ret != EOK) return ret;
DelayKTask(50);
return EOK;
}
x_err_t UsbhHubPortDebounce(UhubPointer hub, uint16 port)
{
x_err_t ret;
int i = 0, times = 20;
uint32 pstatus;
x_bool connect = RET_TRUE;
int delayticks = USB_DEBOUNCE_TIME / times;
if (delayticks < 1)
delayticks = 1;
NULL_PARAM_CHECK(hub);
for(i=0; i<times; i++)
{
ret = UsbhHubGetPortStatus(hub, port, &pstatus);
if(ret != EOK) return ret;
if(!(pstatus & PORT_CCS))
{
connect = RET_FALSE;
break;
}
DelayKTask(delayticks);
}
if(connect) return EOK;
else return -ERROR;
}
static x_err_t UsbhHubPortChange(UhubPointer hub)
{
int i;
x_bool reconnect;
NULL_PARAM_CHECK(hub);
for (i = 0; i < hub->NumPorts; i++)
{
x_err_t ret;
struct uinstance* device;
uint32 pstatus = 0;
reconnect = RET_FALSE;
ret = UsbhHubGetPortStatus(hub, i + 1, &pstatus);
if(ret != EOK) continue;
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("port %d status 0x%x\n", i + 1, pstatus));
if (pstatus & PORT_CCSC)
{
UsbhHubClearPortFeature(hub, i + 1, PORT_FEAT_C_CONNECTION);
reconnect = RET_TRUE;
}
if(pstatus & PORT_PESC)
{
UsbhHubClearPortFeature(hub, i + 1, PORT_FEAT_C_ENABLE);
reconnect = RET_TRUE;
}
if(reconnect)
{
if(hub->child[i] != NONE && hub->child[i]->status != DEV_STATUS_IDLE)
UsbhDetachInstance(hub->child[i]);
ret = UsbhHubPortDebounce(hub, i + 1);
if(ret != EOK) continue;
device = UsbhAllocInstance(hub->hcd);
if(device == NONE) break;
device->speed = (pstatus & PORT_LSDA) ? 1 : 0;
device->parent_hub = hub;
device->hcd = hub->hcd;
device->port = i + 1;
hub->child[i] = device;
UsbhHubResetPort(hub, i + 1);
UsbhAttatchInstance(device);
}
}
return EOK;
}
static void UsbhHubIrq(void* context)
{
upipe_t pipe;
UhubPointer hub;
int timeout = USB_TIMEOUT_BASIC;
if(NONE == context) {
KPrintf("PARAM CHECK FAILED ...%s %d contex is NULL.\n",__FUNCTION__,__LINE__);
return;
}
pipe = (upipe_t)context;
hub = (UhubPointer)pipe->UserData;
if(pipe->status != UPIPE_STATUS_OK)
{
SYS_KDEBUG_LOG(SYS_DEBUG_USB,("hub irq error\n"));
return;
}
UsbhHubPortChange(hub);
SYS_KDEBUG_LOG(SYS_DEBUG_USB,("hub int xfer...\n"));
CHECK(pipe->inst->hcd);
UsbHcdPipeXfer(hub->self->hcd, pipe, hub->buffer, pipe->ep.wMaxPacketSize, timeout);
}
static x_err_t UsbhHubEnable(void *arg)
{
int i = 0;
x_err_t ret = EOK;
UepDescPointer EpDesc = NONE;
UhubPointer hub;
struct uinstance* device;
struct uhintf* intf = (struct uhintf*)arg;
upipe_t pipe_in = NONE;
int timeout = USB_TIMEOUT_LONG;
NULL_PARAM_CHECK(intf);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("usbh_hub_run\n"));
device = intf->device;
hub = x_malloc(sizeof(struct uhub));
memset(hub, 0, sizeof(struct uhub));
intf->UserData = (void*)hub;
ret = UsbhHubGetDescriptor(device, (uint8*)&hub->HubDesc, 8);
if(ret != EOK)
{
KPrintf("get hub descriptor failed\n");
return -ERROR;
}
ret = UsbhHubGetDescriptor(device, (uint8*)&hub->HubDesc,
hub->HubDesc.length);
if(ret != EOK)
{
KPrintf("get hub descriptor again failed\n");
return -ERROR;
}
hub->NumPorts = hub->HubDesc.NumPorts;
hub->hcd = device->hcd;
hub->self = device;
for (i = 0; i < hub->NumPorts; i++)
{
UsbhHubSetPortFeature(hub, i + 1, PORT_FEAT_POWER);
DelayKTask(hub->HubDesc.PwronToGood
* 2 * TICK_PER_SECOND / 1000 );
}
if(intf->IntfDesc->bNumEndpoints != 1)
return -ERROR;
UsbhGetEndpointDescriptor(intf->IntfDesc, 0, &EpDesc);
if(EpDesc == NONE)
{
KPrintf("usb_get_endpoint_descriptor error\n");
return -ERROR;
}
if( USB_EP_ATTR(EpDesc->bmAttributes) == USB_EP_ATTR_INT)
{
if(EpDesc->bEndpointAddress & USB_DIR_IN)
{
pipe_in = UsbInstanceFindPipe(device,EpDesc->bEndpointAddress);
if(pipe_in == NONE)
{
return ERROR;
}
UsbPipeAddCallback(pipe_in,UsbhHubIrq);
}
else return -ERROR;
}
NULL_PARAM_CHECK(device->hcd);
pipe_in->UserData = hub;
UsbHcdPipeXfer(hub->hcd, pipe_in, hub->buffer,
pipe_in->ep.wMaxPacketSize, timeout);
return EOK;
}
static x_err_t UsbhHubDisable(void* arg)
{
int i;
UhubPointer hub;
struct uhintf* intf = (struct uhintf*)arg;
NULL_PARAM_CHECK(intf);
SYS_KDEBUG_LOG(SYS_DEBUG_USB, ("usbh_hub_stop\n"));
hub = (UhubPointer)intf->UserData;
for(i=0; i<hub->NumPorts; i++)
{
if(hub->child[i] != NONE)
UsbhDetachInstance(hub->child[i]);
}
if(hub != NONE) x_free(hub);
if(intf != NONE) x_free(intf);
return EOK;
}
UcdPointer UsbhClassDriverHub(void)
{
HubDriver.ClassCode = USB_CLASS_HUB;
HubDriver.enable = UsbhHubEnable;
HubDriver.disable = UsbhHubDisable;
return &HubDriver;
}
static void UsbhHubThreadEntry(void* parameter)
{
while(RET_TRUE)
{
struct UhostMsg msg;
if(KMsgQueueRecv(UsbMq, &msg, sizeof(struct UhostMsg), WAITING_FOREVER)
!= EOK ) continue;
switch (msg.type)
{
case USB_MSG_CONNECT_CHANGE:
UsbhHubPortChange(msg.content.hub);
break;
case USB_MSG_CALLBACK:
msg.content.cb.function(msg.content.cb.context);
break;
default:
break;
}
}
}
x_err_t UsbhEventSignal(struct UhostMsg* msg)
{
NULL_PARAM_CHECK(msg);
KMsgQueueSend(UsbMq, (void*)msg, sizeof(struct UhostMsg));
return EOK;
}
void UsbhHubInit(UhcdPointer hcd)
{
int32 thread;
RootHub.IsRoothub = RET_TRUE;
hcd->roothub = &RootHub;
RootHub.hcd = hcd;
RootHub.NumPorts = hcd->NumPorts;
UsbMq = KCreateMsgQueue( 32, 16);
thread = KTaskCreate("usbh", UsbhHubThreadEntry, NONE,
USB_THREAD_STACK_SIZE, 8);
if(thread >= 0)
{
StartupKTask(thread);
}
}
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2011-12-12 Yi Qiu first version
*/
/**
* @file usbhost.c
* @brief support usb host function init
* @version 1.0
* @author AIIT XUOS Lab
* @date 2021-04-25
*/
/*************************************************
File name: usbhost.c
Description: support usb host function init
Others: take RT-Thread v4.0.2/components/drivers/usb/usbhost/core/usbhost.c for references
https://github.com/RT-Thread/rt-thread/tree/v4.0.2
History:
1. Date: 2021-04-25
Author: AIIT XUOS Lab
Modification:
1. support usb host driver init
2. support usb bus driver framework
*************************************************/
#include <xiuos.h>
#include <usb_host.h>
#define USB_HOST_CONTROLLER_NAME "usbh"
x_err_t UsbHostInit(struct uhcd *hcd)
{
UcdPointer drv;
UsbhHubInit((UhcdPointer)hcd);
UsbhClassDriverInit();
#ifdef USBH_MSTORAGE
drv = UsbhClassDriverStorage();
UsbhClassDriverRegister(drv);
#endif
drv = UsbhClassDriverHub();
UsbhClassDriverRegister(drv);
return EOK;
}