refactor(platform): update platform support

This commit is contained in:
sakumisu
2024-05-23 23:14:53 +08:00
parent 3336919e0d
commit 865d2f5d96
25 changed files with 1431 additions and 365 deletions

189
platform/nuttx/usbh_fs.c Normal file
View File

@@ -0,0 +1,189 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <nuttx/config.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/irq.h>
#include <nuttx/kmalloc.h>
#include <nuttx/signal.h>
#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include <nuttx/scsi.h>
#include <nuttx/fs/fs.h>
#include <nuttx/mutex.h>
#include "usbh_core.h"
#include "usbh_msc.h"
#ifdef CONFIG_ARCH_CHIP_HPMICRO
#include "hpm_misc.h"
#define usbhmsc_phy2sysaddr(a) core_local_mem_to_sys_address(0, a)
#else
#define usbhmsc_phy2sysaddr(a) (a)
#endif
static int usbhost_open(FAR struct inode *inode);
static int usbhost_close(FAR struct inode *inode);
static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
blkcnt_t startsector, unsigned int nsectors);
static ssize_t usbhost_write(FAR struct inode *inode,
FAR const unsigned char *buffer,
blkcnt_t startsector, unsigned int nsectors);
static int usbhost_geometry(FAR struct inode *inode,
FAR struct geometry *geometry);
static int usbhost_ioctl(FAR struct inode *inode, int cmd, unsigned long arg);
/* Block driver operations. This is the interface exposed to NuttX by the
* class that permits it to behave like a block driver.
*/
static const struct block_operations g_bops = {
usbhost_open, /* open */
usbhost_close, /* close */
usbhost_read, /* read */
usbhost_write, /* write */
usbhost_geometry, /* geometry */
usbhost_ioctl /* ioctl */
};
static int usbhost_open(FAR struct inode *inode)
{
struct usbh_msc *msc_class;
DEBUGASSERT(inode->i_private);
msc_class = (struct usbh_msc *)inode->i_private;
if (msc_class->hport && msc_class->hport->connected) {
return OK;
} else {
return -ENODEV;
}
}
static int usbhost_close(FAR struct inode *inode)
{
DEBUGASSERT(inode->i_private);
return 0;
}
static ssize_t usbhost_read(FAR struct inode *inode, unsigned char *buffer,
blkcnt_t startsector, unsigned int nsectors)
{
struct usbh_msc *msc_class;
int ret;
DEBUGASSERT(inode->i_private);
msc_class = (struct usbh_msc *)inode->i_private;
if (msc_class->hport && msc_class->hport->connected) {
ret = usbh_msc_scsi_read10(msc_class, startsector, (uint8_t *)usbhmsc_phy2sysaddr((uint32_t)buffer), nsectors);
if (ret < 0) {
return ret;
} else {
#ifdef CONFIG_USBHOST_MSC_DCACHE
up_invalidate_dcache((uintptr_t)buffer, (uintptr_t)(buffer + nsectors * msc_class->blocksize));
#endif
return nsectors;
}
} else {
return -ENODEV;
}
}
static ssize_t usbhost_write(FAR struct inode *inode,
FAR const unsigned char *buffer,
blkcnt_t startsector, unsigned int nsectors)
{
struct usbh_msc *msc_class;
int ret;
DEBUGASSERT(inode->i_private);
msc_class = (struct usbh_msc *)inode->i_private;
if (msc_class->hport && msc_class->hport->connected) {
#ifdef CONFIG_USBHOST_MSC_DCACHE
up_flush_dcache((uintptr_t)buffer, (uintptr_t)(buffer + nsectors * msc_class->blocksize));
#endif
ret = usbh_msc_scsi_write10(msc_class, startsector, (uint8_t *)usbhmsc_phy2sysaddr((uint32_t)buffer), nsectors);
if (ret < 0) {
return ret;
} else {
return nsectors;
}
} else {
return -ENODEV;
}
}
static int usbhost_geometry(FAR struct inode *inode,
FAR struct geometry *geometry)
{
struct usbh_msc *msc_class;
DEBUGASSERT(inode->i_private);
msc_class = (struct usbh_msc *)inode->i_private;
if (msc_class->hport && msc_class->hport->connected) {
memset(geometry, 0, sizeof(*geometry));
geometry->geo_available = true;
geometry->geo_mediachanged = false;
geometry->geo_writeenabled = true;
geometry->geo_nsectors = msc_class->blocknum;
geometry->geo_sectorsize = msc_class->blocksize;
uinfo("nsectors: %" PRIdOFF " sectorsize: %" PRIi16 "\n",
geometry->geo_nsectors, geometry->geo_sectorsize);
return OK;
} else {
return -ENODEV;
}
return 0;
}
static int usbhost_ioctl(FAR struct inode *inode, int cmd, unsigned long arg)
{
struct usbh_msc *msc_class;
DEBUGASSERT(inode->i_private);
msc_class = (struct usbh_msc *)inode->i_private;
if (msc_class->hport && msc_class->hport->connected) {
return -ENOTTY;
} else {
return -ENODEV;
}
return 0;
}
#define DEV_FORMAT "/dev/sd%c"
void usbh_msc_run(struct usbh_msc *msc_class)
{
char devname[32];
snprintf(devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
register_blockdriver(devname, &g_bops, 0, msc_class);
}
void usbh_msc_stop(struct usbh_msc *msc_class)
{
char devname[32];
snprintf(devname, CONFIG_USBHOST_DEV_NAMELEN, DEV_FORMAT, msc_class->sdchar);
unregister_blockdriver(devname);
}

165
platform/nuttx/usbh_net.c Normal file
View File

@@ -0,0 +1,165 @@
/*
* Copyright (c) 2024, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <nuttx/config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <semaphore.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/net/ip.h>
#include <nuttx/net/netdev.h>
#include "usbh_core.h"
#define CONFIG_USBHOST_PLATFORM_CDC_ECM
#define CONFIG_USBHOST_PLATFORM_CDC_RNDIS
#define CONFIG_USBHOST_PLATFORM_CDC_NCM
#define CONFIG_USBHOST_PLATFORM_ASIX
#define CONFIG_USBHOST_PLATFORM_RTL8152
struct usbh_net {
struct net_driver_s netdev;
struct work_s txpollwork;
bool linkup;
};
void usbh_net_eth_input_common(struct net_driver_s *dev, uint8_t *buf, size_t len, int (*eth_output)(uint8_t *buf, uint32_t buflen))
{
FAR struct eth_hdr_s *hdr;
net_lock();
NETDEV_RXPACKETS(dev);
/* Any ACK or other response packet generated by the network stack
* will always be shorter than the received packet, therefore it is
* safe to pass the received frame buffer directly.
*/
dev->d_buf = buf;
dev->d_len = len;
hdr = (FAR struct eth_hdr_s *)dev->d_buf;
#ifdef CONFIG_NET_IPv4
if (hdr->type == HTONS(ETHTYPE_IP)) {
NETDEV_RXIPV4(dev);
/* Receive an IPv4 packet from the network device */
ipv4_input(dev);
if (dev->d_len > 0) {
/* And send the packet */
eth_output(dev->d_buf, dev->d_len);
}
} else
#endif
#ifdef CONFIG_NET_IPv6
if (hdr->type == HTONS(ETHTYPE_IP6)) {
NETDEV_RXIPV6(dev);
/* Give the IPv6 packet to the network layer */
ipv6_input(dev);
if (dev->d_len > 0) {
/* And send the packet */
eth_output(dev->d_buf, dev->d_len);
}
} else
#endif
#ifdef CONFIG_NET_ARP
if (hdr->type == HTONS(ETHTYPE_ARP)) {
NETDEV_RXARP(dev);
arp_input(dev);
if (dev->d_len > 0) {
eth_output(dev->d_buf, dev->d_len);
}
} else
#endif
{
NETDEV_RXDROPPED(dev);
}
net_unlock();
}
#ifdef CONFIG_USBHOST_PLATFORM_CDC_RNDIS
#include "usbh_rndis.h"
struct usbh_net g_rndis_dev;
static int rndis_ifup(struct net_driver_s *dev)
{
printf("rndis if up\r\n");
g_rndis_dev.linkup = true;
usb_osal_thread_create("usbh_rndis_rx", 2048, CONFIG_USBHOST_PSC_PRIO + 1, usbh_rndis_rx_thread, NULL);
return OK;
}
static int rndis_ifdown(struct net_driver_s *dev)
{
printf("rndis if down\r\n");
g_rndis_dev.linkup = false;
return OK;
}
static int rndis_txpoll(struct net_driver_s *dev)
{
return usbh_rndis_eth_output(g_rndis_dev.netdev.d_buf, g_rndis_dev.netdev.d_len);
}
static void rndis_txavail_work(void *arg)
{
net_lock();
if (g_rndis_dev.linkup) {
devif_poll(&g_rndis_dev.netdev, rndis_txpoll);
} else {
}
net_unlock();
}
static int rndis_txavail(struct net_driver_s *dev)
{
if (work_available(&g_rndis_dev.txpollwork)) {
work_queue(LPWORK, &g_rndis_dev.txpollwork, rndis_txavail_work, NULL, 0);
} else {
return -1;
}
return OK;
}
void usbh_rndis_eth_input(uint8_t *buf, uint32_t buflen)
{
usbh_net_eth_input_common(&g_rndis_dev.netdev, buf, buflen, usbh_rndis_eth_output);
}
void usbh_rndis_run(struct usbh_rndis *rndis_class)
{
memset(&g_rndis_dev.netdev, 0, sizeof(struct net_driver_s));
g_rndis_dev.netdev.d_ifup = rndis_ifup;
g_rndis_dev.netdev.d_ifdown = rndis_ifdown;
g_rndis_dev.netdev.d_txavail = rndis_txavail;
g_rndis_dev.netdev.d_private = rndis_class;
for (uint8_t j = 0; j < 6; j++) {
g_rndis_dev.netdev.d_mac.ether.ether_addr_octet[j] = rndis_class->mac[j];
}
netdev_register(&g_rndis_dev.netdev, NET_LL_ETHERNET);
}
void usbh_rndis_stop(struct usbh_rndis *rndis_class)
{
}
#endif