refactor(platform): update platform support
This commit is contained in:
189
platform/nuttx/usbh_fs.c
Normal file
189
platform/nuttx/usbh_fs.c
Normal 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
165
platform/nuttx/usbh_net.c
Normal 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
|
||||
Reference in New Issue
Block a user