dde_linux: remove legacy_usb_net

issue #4958
This commit is contained in:
Sebastian Sumpf 2023-08-18 19:55:09 +02:00 committed by Christian Helmuth
parent cd2910eb2c
commit 7e823f7c19
17 changed files with 1 additions and 3571 deletions

View File

@ -1,13 +0,0 @@
USB_NET_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_net
include $(call select_from_repositories,lib/import/import-usb_arch_include.mk)
#
# The order of include-search directories is important, we need to look into
# 'contrib' before falling back to our custom 'lx_emul.h' header.
#
INC_DIR += $(ARCH_SRC_INC_DIR)
INC_DIR += $(USB_NET_CONTRIB_DIR)/include
#INC_DIR += $(USB_NET_CONTRIB_DIR)/drivers/hid
#INC_DIR += $(USB_NET_CONTRIB_DIR)/drivers/input
INC_DIR += $(LIB_CACHE_DIR)/usb_net_include/include/include/include

View File

@ -1,37 +0,0 @@
ifeq ($(called_from_lib_mk),yes)
USB_NET_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_net
LX_EMUL_H := $(REP_DIR)/src/drivers/legacy_usb_net/lx_emul.h
#
# Determine the header files included by the contrib code. For each
# of these header files we create a symlink to 'lx_emul.h'.
#
SCAN_DIRS := $(addprefix $(USB_NET_CONTRIB_DIR)/include/, asm-generic linux uapi net) \
$(addprefix $(USB_NET_CONTRIB_DIR)/, drivers net lib)
GEN_INCLUDES := $(shell grep -rIh "^\#include .*\/" $(SCAN_DIRS) |\
sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" |\
sort | uniq)
#
# Filter out original Linux headers that exist in the contrib directory
#
NO_GEN_INCLUDES := $(shell cd $(USB_NET_CONTRIB_DIR)/; find include -name "*.h" |\
sed "s/.\///" | sed "s/.*include\///")
GEN_INCLUDES := $(filter-out $(NO_GEN_INCLUDES),$(GEN_INCLUDES))
#
# Put Linux headers in 'GEN_INC' dir, since some include use "../../" paths use
# three level include hierarchy
#
GEN_INC := $(shell pwd)/include/include/include
GEN_INCLUDES := $(addprefix $(GEN_INC)/,$(GEN_INCLUDES))
all: $(GEN_INCLUDES)
$(GEN_INCLUDES):
$(VERBOSE)mkdir -p $(dir $@)
$(VERBOSE)ln -s $(LX_EMUL_H) $@
endif
CC_CXX_WARN_STRICT =

View File

@ -1,38 +0,0 @@
PORT_DIR := $(call port_dir,$(REP_DIR)/ports/dde_linux)
MIRROR_FROM_REP_DIR := src/drivers/legacy_usb_net \
src/drivers/nic/linux_network_session_base.cc \
src/drivers/nic/linux_network_session_base.h \
src/lib/legacy/lx_kit \
src/lib/lx_kit/spec \
src/include/legacy \
lib/import/import-usb_net_include.mk \
lib/import/import-usb_arch_include.mk \
lib/mk/usb_net_include.mk \
$(foreach SPEC, \
arm arm_64 arm_v6 arm_v7 x86 x86_32 x86_64, \
src/include/spec/$(SPEC)) \
$(foreach SPEC, \
arm arm_64 x86_32 x86_64, \
lib/mk/spec/$(SPEC)/lx_kit_setjmp.mk)
MIRROR_FROM_PORT_DIR := $(shell cd $(PORT_DIR); \
find src/drivers/usb_net -type f | \
grep -v ".git")
MIRROR_FROM_PORT_DIR := $(filter-out $(MIRROR_FROM_REP_DIR), \
$(MIRROR_FROM_PORT_DIR))
content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_PORT_DIR)
$(MIRROR_FROM_REP_DIR):
$(mirror_from_rep_dir)
$(MIRROR_FROM_PORT_DIR):
mkdir -p $(dir $@)
cp $(PORT_DIR)/$@ $@
content: LICENSE
LICENSE:
( echo "GNU General Public License version 2, see:"; \
echo "https://www.kernel.org/pub/linux/kernel/COPYING" ) > $@

View File

@ -1 +0,0 @@
2023-08-21 1a1be9d8df290e48fdb5539bef1c23367b596955

View File

@ -1,8 +0,0 @@
base
os
format
nic_session
uplink_session
usb_session
timer_session
nic_driver

View File

@ -10,7 +10,7 @@
create_boot_directory
import_from_depot [depot_user]/src/[base_src] \
[depot_user]/pkg/test_usb_host_drv-[board] \
[depot_user]/src/legacy_usb_net_drv \
[depot_user]/src/usb_net_drv \
[depot_user]/src/nic_router \
[depot_user]/src/libc \
[depot_user]/src/vfs \

View File

@ -1,20 +0,0 @@
USB NIC driver
##############
Driver for network interface cards connected via USB.
Configuration snippet:
!<start name="usb_net_drv">
! <resource name="RAM" quantum="10M"/>
! <provides> <service name="Nic"/> </provides>
! <config mac="2e:60:90:0c:4e:01" />
!</start>
There is the 'mac' attribute where one can specify the hardware address of
the network interface. This is necessary in case the EEPROM of the network card
cannot be accessed via the host controller making it impossible to retrieve the
devices hardware address. If this is the case and no 'mac' attribute is given a
fallback address will be assigned to the network device. Note that the fallback
address will always be the same.

View File

@ -1,172 +0,0 @@
/*
* \brief USB net driver
* \author Stefan Kalkowski
* \date 2018-06-27
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _SRC__DRIVERS__USB_NET__DRIVER_H_
#define _SRC__DRIVERS__USB_NET__DRIVER_H_
/* Genode includes */
#include <base/allocator_avl.h>
#include <base/attached_rom_dataspace.h>
#include <base/heap.h>
#include <usb_session/connection.h>
#include <util/reconstructible.h>
/* local includes */
#include <uplink_client.h>
/* Linux emulation environment includes */
#include <legacy/lx_kit/scheduler.h>
#include <lx_emul.h>
#include <legacy/lx_emul/extern_c_begin.h>
#include <linux/usb.h>
#include <legacy/lx_emul/extern_c_end.h>
struct usb_device_id;
struct usb_interface;
struct usb_device;
struct Driver
{
using Label = Genode::String<64>;
struct Task
{
Lx::Task task;
Genode::Signal_handler<Task> handler;
void handle_signal()
{
task.unblock();
Lx::scheduler().schedule();
}
template <typename... ARGS>
Task(Genode::Entrypoint & ep, ARGS &&... args)
: task(args...), handler(ep, *this, &Task::handle_signal) {}
};
struct Device
{
using Le = Genode::List_element<Device>;
Le le { this };
Label label;
Driver &driver;
Genode::Env &env;
Genode::Allocator_avl &alloc;
Task state_task;
Task urb_task;
Usb::Connection usb { env, &alloc, label.string(),
512 * 1024, state_task.handler };
usb_device * udev = nullptr;
bool updated = true;
Device(Driver & drv, Label label);
~Device();
static void state_task_entry(void *);
static void urb_task_entry(void *);
void register_device();
void unregister_device();
void scan_interfaces(unsigned iface_idx);
void scan_altsettings(usb_interface * iface,
unsigned iface_idx, unsigned alt_idx);
void probe_interface(usb_interface *, usb_device_id *);
void remove_interface(usb_interface *);
};
struct Devices : Genode::List<Device::Le>
{
template <typename FN>
void for_each(FN const & fn)
{
Device::Le * cur = first();
for (Device::Le * next = cur ? cur->next() : nullptr; cur;
cur = next, next = cur ? cur->next() : nullptr)
fn(*cur->object());
}
};
class Sync_packet : public Usb::Completion
{
private:
Usb::Session_client & _usb;
Usb::Packet_descriptor _packet { _usb.alloc_packet(0) };
completion _comp;
public:
Sync_packet(Usb::Session_client &usb) : _usb(usb)
{
init_completion(&_comp);
}
virtual ~Sync_packet()
{
_usb.source()->release_packet(_packet);
}
void complete(Usb::Packet_descriptor &p) override
{
::complete(&_comp);
}
void send()
{
_packet.completion = this;
_usb.source()->submit_packet(_packet);
wait_for_completion(&_comp);
}
void config(int configuration)
{
_packet.type = Usb::Packet_descriptor::CONFIG;
_packet.number = configuration;
send();
}
void alt_setting(int interface, int alt_setting)
{
_packet.type = Usb::Packet_descriptor::ALT_SETTING;
_packet.interface.number = interface;
_packet.interface.alt_setting = alt_setting;
send();
}
};
Devices devices;
Genode::Env &env;
Genode::Entrypoint &ep { env.ep() };
Genode::Attached_rom_dataspace config_rom { env, "config" };
Genode::Heap heap { env.ram(), env.rm() };
Genode::Allocator_avl alloc { &heap };
Genode::Constructible<Genode::Uplink_client> uplink_client { };
Genode::Constructible<Task> main_task;
Genode::Constructible<Genode::Attached_rom_dataspace> report_rom;
Driver(Genode::Env &env);
void activate_network_session()
{
uplink_client.construct(
env, heap,
config_rom.xml().attribute_value(
"uplink_label", Genode::Session_label::String { "" }));
}
static void main_task_entry(void *);
};
#endif /* _SRC__DRIVERS__USB_HID__DRIVER_H_ */

View File

@ -1,465 +0,0 @@
#include <lx_emul.h>
#if 0
#define TRACE \
do { \
lx_printf("%s not implemented\n", __func__); \
} while (0)
#else
#define TRACE do { ; } while (0)
#endif
#define TRACE_AND_STOP \
do { \
lx_printf("%s not implemented\n", __func__); \
BUG(); \
} while (0)
struct page *alloc_pages(gfp_t gfp_mask, unsigned int order)
{
TRACE_AND_STOP;
return NULL;
}
u16 bitrev16(u16 in)
{
TRACE_AND_STOP;
return -1;
}
u16 crc16(u16 crc, const u8 *buffer, size_t len)
{
TRACE_AND_STOP;
return -1;
}
__sum16 csum_fold(__wsum csum)
{
TRACE_AND_STOP;
return -1;
}
__wsum csum_partial(const void *buff, int len, __wsum sum)
{
TRACE_AND_STOP;
return -1;
}
int device_set_wakeup_enable(struct device *dev, bool enable)
{
TRACE_AND_STOP;
return -1;
}
void dst_release(struct dst_entry *dst)
{
TRACE_AND_STOP;
}
struct net_device;
u32 ethtool_op_get_link(struct net_device *dev)
{
TRACE_AND_STOP;
return -1;
}
int ethtool_op_get_ts_info(struct net_device *dev, struct ethtool_ts_info *eti)
{
TRACE_AND_STOP;
return -1;
}
bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap)
{
TRACE_AND_STOP;
return -1;
}
void free_uid(struct user_struct * user)
{
TRACE_AND_STOP;
}
struct mii_if_info;
int generic_mii_ioctl(struct mii_if_info *mii_if, struct mii_ioctl_data *mii_data, int cmd, unsigned int *duplex_changed)
{
TRACE_AND_STOP;
return -1;
}
void get_page(struct page *page)
{
TRACE_AND_STOP;
}
bool gfpflags_allow_blocking(const gfp_t gfp_flags)
{
TRACE_AND_STOP;
return -1;
}
bool gfp_pfmemalloc_allowed(gfp_t gfp_flags)
{
TRACE_AND_STOP;
return -1;
}
int in_irq()
{
TRACE_AND_STOP;
return -1;
}
void *kmap_atomic(struct page *page)
{
TRACE_AND_STOP;
return NULL;
}
int memcmp(const void *s1, const void *s2, size_t size)
{
TRACE_AND_STOP;
return -1;
}
void mii_ethtool_get_link_ksettings( struct mii_if_info *mii, struct ethtool_link_ksettings *cmd)
{
TRACE_AND_STOP;
}
int mii_ethtool_set_link_ksettings( struct mii_if_info *mii, const struct ethtool_link_ksettings *cmd)
{
TRACE_AND_STOP;
return -1;
}
unsigned netdev_mc_count(struct net_device * dev)
{
TRACE;
return 1;
}
int netdev_mc_empty(struct net_device * ndev)
{
TRACE;
return 1;
}
void netdev_stats_to_stats64(struct rtnl_link_stats64 *stats64, const struct net_device_stats *netdev_stats)
{
TRACE_AND_STOP;
}
bool netdev_uses_dsa(struct net_device *dev)
{
TRACE;
return false;
}
void netif_device_attach(struct net_device *dev)
{
TRACE;
}
void netif_device_detach(struct net_device *dev)
{
TRACE_AND_STOP;
}
int netif_device_present(struct net_device * d)
{
TRACE;
return 1;
}
u32 netif_msg_init(int arg0, int arg1)
{
TRACE;
return 0;
}
void netif_start_queue(struct net_device *dev)
{
TRACE;
}
void netif_stop_queue(struct net_device *dev)
{
TRACE;
}
void netif_trans_update(struct net_device *dev)
{
TRACE;
}
void netif_tx_wake_all_queues(struct net_device *dev)
{
TRACE_AND_STOP;
}
void netif_wake_queue(struct net_device * d)
{
TRACE;
}
const void *of_get_mac_address(struct device_node *np)
{
TRACE;
return NULL;
}
void pm_runtime_enable(struct device *dev)
{
TRACE;
}
void read_lock_bh(rwlock_t * l)
{
TRACE_AND_STOP;
}
void read_unlock_bh(rwlock_t * l)
{
TRACE_AND_STOP;
}
void secpath_reset(struct sk_buff * skb)
{
TRACE;
}
void __set_current_state(int state)
{
TRACE;
}
void sg_init_table(struct scatterlist *sg, unsigned int arg)
{
TRACE_AND_STOP;
}
void sg_set_buf(struct scatterlist *sg, const void *buf, unsigned int buflen)
{
TRACE_AND_STOP;
}
void sg_set_page(struct scatterlist *sg, struct page *page, unsigned int len, unsigned int offset)
{
TRACE_AND_STOP;
}
void sk_free(struct sock *sk)
{
TRACE_AND_STOP;
}
void sock_efree(struct sk_buff *skb)
{
TRACE_AND_STOP;
}
void spin_lock_irq(spinlock_t *lock)
{
TRACE_AND_STOP;
}
void spin_lock_nested(spinlock_t *lock, int subclass)
{
TRACE;
}
void spin_unlock_irq(spinlock_t *lock)
{
TRACE_AND_STOP;
}
size_t strlcpy(char *dest, const char *src, size_t size)
{
TRACE_AND_STOP;
return -1;
}
void tasklet_kill(struct tasklet_struct *t)
{
TRACE;
}
void trace_consume_skb(struct sk_buff *skb)
{
TRACE;
}
void trace_kfree_skb(struct sk_buff *skb, void *arg)
{
TRACE;
}
unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync *p)
{
TRACE_AND_STOP;
return -1;
}
bool u64_stats_fetch_retry_irq(const struct u64_stats_sync *p, unsigned int s)
{
TRACE_AND_STOP;
return -1;
}
struct usb_device;
int usb_clear_halt(struct usb_device *dev, int pipe)
{
TRACE_AND_STOP;
return -1;
}
struct usb_driver;
struct usb_interface;
void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface)
{
TRACE;
}
/* only called to kill interrupt urb in usbnet.c */
struct urb;
void usb_kill_urb(struct urb *urb)
{
TRACE;
}
struct usb_anchor;
struct urb *usb_get_from_anchor(struct usb_anchor *anchor)
{
TRACE_AND_STOP;
return NULL;
}
int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout)
{
TRACE_AND_STOP;
return -1;
}
void usb_scuttle_anchored_urbs(struct usb_anchor *anchor)
{
TRACE;
}
ktime_t ktime_get_real(void)
{
TRACE_AND_STOP;
return -1;
}
void kunmap_atomic(void *addr)
{
TRACE_AND_STOP;
}
void might_sleep()
{
TRACE_AND_STOP;
}
bool page_is_pfmemalloc(struct page *page)
{
TRACE_AND_STOP;
return -1;
}
void put_page(struct page *page)
{
TRACE_AND_STOP;
}
int usb_unlink_urb(struct urb *urb)
{
TRACE;
return 0;
}
struct urb *usb_get_urb(struct urb *urb)
{
TRACE;
return NULL;
}
void usleep_range(unsigned long min, unsigned long max)
{
TRACE;
}
void phy_stop(struct phy_device *phydev)
{
TRACE;
}
void phy_disconnect(struct phy_device *phydev)
{
TRACE;
}
void phy_print_status(struct phy_device *phydev)
{
TRACE;
}
int phy_mii_ioctl(struct phy_device *phydev, struct ifreq *ifr, int cmd)
{
TRACE;
return 0;
}
typedef int phy_interface_t;
struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, void (*handler)(struct net_device *), phy_interface_t interface)
{
TRACE;
return 0;
}
int genphy_resume(struct phy_device *phydev) { TRACE; return 0; }
void phy_start(struct phy_device *phydev) { TRACE; }
struct mii_bus;
void mdiobus_free(struct mii_bus *bus) { TRACE; }
void mdiobus_unregister(struct mii_bus *bus) { TRACE; }
struct mii_bus *mdiobus_alloc_size(size_t size)
{
TRACE_AND_STOP;
return NULL;
}
int __mdiobus_register(struct mii_bus *bus, struct module *owner)
{
TRACE_AND_STOP;
return -1;
}
int phy_ethtool_get_link_ksettings(struct net_device *ndev, struct ethtool_link_ksettings *cmd)
{
TRACE_AND_STOP;
return -1;
}
int phy_ethtool_set_link_ksettings(struct net_device *ndev, const struct ethtool_link_ksettings *cmd)
{
TRACE_AND_STOP;
return -1;
}
int phy_ethtool_nway_reset(struct net_device *ndev)
{
TRACE_AND_STOP;
return -1;
}
int sysctl_tstamp_allow_data;
struct user_namespace init_user_ns;

View File

@ -1,622 +0,0 @@
#include <base/env.h>
#include <usb_session/client.h>
#include <format/snprintf.h>
#include <nic_session/nic_session.h>
#include <util/xml_node.h>
#include <driver.h>
#include <lx_emul.h>
#include <legacy/lx_emul/extern_c_begin.h>
#include <linux/usb.h>
#include <legacy/lx_emul/extern_c_end.h>
#define TRACE do { ; } while (0)
#include <legacy/lx_emul/impl/kernel.h>
#include <legacy/lx_emul/impl/delay.h>
#include <legacy/lx_emul/impl/slab.h>
#include <legacy/lx_emul/impl/work.h>
#include <legacy/lx_emul/impl/spinlock.h>
#include <legacy/lx_emul/impl/mutex.h>
#include <legacy/lx_emul/impl/sched.h>
#include <legacy/lx_emul/impl/timer.h>
#include <legacy/lx_emul/impl/completion.h>
#include <legacy/lx_emul/impl/wait.h>
#include <legacy/lx_emul/impl/usb.h>
#include <legacy/lx_kit/backend_alloc.h>
#include <legacy/lx_emul/extern_c_begin.h>
#include <linux/mii.h>
#include <linux/usb/usbnet.h>
static int usb_match_device(struct usb_device *dev,
const struct usb_device_id *id)
{
if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
id->idVendor != le16_to_cpu(dev->descriptor.idVendor))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
id->idProduct != le16_to_cpu(dev->descriptor.idProduct))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
(id->bcdDevice_lo > le16_to_cpu(dev->descriptor.bcdDevice)))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
(id->bcdDevice_hi < le16_to_cpu(dev->descriptor.bcdDevice)))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
(id->bDeviceClass != dev->descriptor.bDeviceClass))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
(id->bDeviceSubClass != dev->descriptor.bDeviceSubClass))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
return 0;
return 1;
}
static int usb_match_one_id_intf(struct usb_device *dev,
struct usb_host_interface *intf,
const struct usb_device_id *id)
{
if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
!(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
(id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS |
USB_DEVICE_ID_MATCH_INT_PROTOCOL |
USB_DEVICE_ID_MATCH_INT_NUMBER)))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
(id->bInterfaceClass != intf->desc.bInterfaceClass))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
(id->bInterfaceSubClass != intf->desc.bInterfaceSubClass))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
(id->bInterfaceProtocol != intf->desc.bInterfaceProtocol))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER) &&
(id->bInterfaceNumber != intf->desc.bInterfaceNumber))
return 0;
return 1;
}
int usb_match_one_id(struct usb_interface *interface,
const struct usb_device_id *id)
{
struct usb_host_interface *intf;
struct usb_device *dev;
if (id == NULL)
return 0;
intf = interface->cur_altsetting;
dev = interface_to_usbdev(interface);
if (!usb_match_device(dev, id))
return 0;
return usb_match_one_id_intf(dev, intf, id);
}
#include <legacy/lx_emul/extern_c_end.h>
class Addr_to_page_mapping : public Genode::List<Addr_to_page_mapping>::Element
{
private:
struct page *_page { nullptr };
static Genode::List<Addr_to_page_mapping> & _list()
{
static Genode::List<Addr_to_page_mapping> _l;
return _l;
}
public:
Addr_to_page_mapping(struct page *page)
: _page(page) { }
static void insert(struct page * page)
{
Addr_to_page_mapping *m = (Addr_to_page_mapping*)
Lx::Malloc::mem().alloc(sizeof (Addr_to_page_mapping));
m->_page = page;
_list().insert(m);
}
static struct page * remove(unsigned long addr)
{
for (Addr_to_page_mapping *m = _list().first(); m; m = m->next())
if ((unsigned long)m->_page->addr == addr) {
struct page * ret = m->_page;
_list().remove(m);
Lx::Malloc::mem().free(m);
return ret;
}
return nullptr;
}
};
struct Lx_driver
{
using Element = Genode::List_element<Lx_driver>;
using List = Genode::List<Element>;
usb_driver & drv;
Element le { this };
Lx_driver(usb_driver & drv) : drv(drv) { list().insert(&le); }
usb_device_id * match(usb_interface * iface)
{
struct usb_device_id * id = const_cast<usb_device_id*>(drv.id_table);
for (; id->idVendor || id->idProduct || id->bDeviceClass ||
id->bInterfaceClass || id->driver_info; id++)
if (usb_match_one_id(iface, id)) return id;
return nullptr;
}
int probe(usb_interface * iface, usb_device_id * id)
{
iface->dev.driver = &drv.drvwrap.driver;
if (drv.probe) return drv.probe(iface, id);
return 0;
}
static List & list()
{
static List _list;
return _list;
}
};
struct task_struct *current;
struct workqueue_struct *system_wq;
unsigned long jiffies;
Genode::Ram_dataspace_capability Lx::backend_alloc(Genode::addr_t size,
Genode::Cache cache)
{
return Lx_kit::env().env().ram().alloc(size, cache);
}
int usb_register_driver(struct usb_driver * driver, struct module *, const char *)
{
INIT_LIST_HEAD(&driver->dynids.list);
if (driver) new (Lx::Malloc::mem()) Lx_driver(*driver);
return 0;
}
Genode::addr_t Lx::backend_dma_addr(Genode::Ram_dataspace_capability)
{
return 0;
}
int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *priv)
{
usb_device *udev = interface_to_usbdev(iface);
Usb::Connection *usb = reinterpret_cast<Usb::Connection *>(udev->bus->controller);
try {
usb->claim_interface(iface->cur_altsetting->desc.bInterfaceNumber);
} catch (...) {
return -1;
}
return 0;
}
int usb_set_interface(struct usb_device *udev, int ifnum, int alternate)
{
Usb::Connection *usb = reinterpret_cast<Usb::Connection *>(udev->bus->controller);
Driver::Sync_packet packet { *usb };
packet.alt_setting(ifnum, alternate);
usb_interface *iface = udev->config->interface[ifnum];
iface->cur_altsetting = &iface->altsetting[alternate];
return 0;
}
void Driver::Device::probe_interface(usb_interface * iface, usb_device_id * id)
{
using Le = Genode::List_element<Lx_driver>;
for (Le *le = Lx_driver::list().first(); le; le = le->next()) {
usb_device_id * id = le->object()->match(iface);
if (id) {
int ret = le->object()->probe(iface, id);
if (ret == 0) return;
}
}
}
void Driver::Device::remove_interface(usb_interface * iface)
{
/* we might not drive this interface */
if (iface->dev.driver) {
usbnet *dev =(usbnet* )usb_get_intfdata(iface);
usbnet_link_change(dev, 0, 0);
to_usb_driver(iface->dev.driver)->disconnect(iface);
}
for (unsigned i = 0; i < iface->num_altsetting; i++) {
if (iface->altsetting[i].extra)
kfree(iface->altsetting[i].extra);
kfree(iface->altsetting[i].endpoint);
}
kfree(iface->altsetting);
kfree(iface);
}
long __wait_completion(struct completion *work, unsigned long timeout)
{
Lx::timer_update_jiffies();
struct process_timer timer { *Lx::scheduler().current() };
unsigned long expire = timeout + jiffies;
if (timeout) {
timer_setup(&timer.timer, process_timeout, 0);
mod_timer(&timer.timer, expire);
}
while (!work->done) {
if (timeout && expire <= jiffies) return 0;
Lx::Task * task = Lx::scheduler().current();
work->task = (void *)task;
task->block_and_schedule();
}
if (timeout) del_timer(&timer.timer);
work->done = 0;
return (expire > jiffies) ? (expire - jiffies) : 1;
}
u16 get_unaligned_le16(const void *p)
{
const struct __una_u16 *ptr = (const struct __una_u16 *)p;
return ptr->x;
}
u32 get_unaligned_le32(const void *p)
{
const struct __una_u32 *ptr = (const struct __una_u32 *)p;
return ptr->x;
}
enum { MAC_LEN = 17 };
static void snprint_mac(char *buf, u8 *mac)
{
for (int i = 0; i < ETH_ALEN; i++) {
Format::snprintf((char *)&buf[i * 3], 3, "%02x", mac[i]);
if ((i * 3) < MAC_LEN)
buf[(i * 3) + 2] = ':';
}
buf[MAC_LEN] = 0;
}
static void random_ether_addr(u8 *addr)
{
using namespace Genode;
char str[MAC_LEN + 1];
u8 fallback[] = { 0x2e, 0x60, 0x90, 0x0c, 0x4e, 0x01 };
Nic::Mac_address mac;
Xml_node config_node = Lx_kit::env().config_rom().xml();
/* try using configured mac */
try {
Xml_node::Attribute mac_node = config_node.attribute("mac");
mac_node.value(mac);
} catch (...) {
/* use fallback mac */
snprint_mac(str, fallback);
Genode::warning("No mac address or wrong format attribute in <nic> - using fallback (", Genode::Cstring(str), ")");
Genode::memcpy(addr, fallback, ETH_ALEN);
return;
}
/* use configured mac*/
Genode::memcpy(addr, mac.addr, ETH_ALEN);
snprint_mac(str, (u8 *)mac.addr);
Genode::log("Using configured mac: ", Genode::Cstring(str));
}
void eth_hw_addr_random(struct net_device *dev)
{
random_ether_addr(dev->dev_addr);
}
void eth_random_addr(u8 *addr)
{
random_ether_addr(addr);
}
struct net_device *alloc_etherdev(int sizeof_priv)
{
net_device *dev = (net_device*) kzalloc(sizeof(net_device), 0);
dev->mtu = 1500;
dev->hard_header_len = 0;
dev->priv = kzalloc(sizeof_priv, 0);
dev->dev_addr = (unsigned char*) kzalloc(ETH_ALEN, 0);
//memset(dev->_dev_addr, 0, sizeof(dev->_dev_addr));
return dev;
}
void free_netdev(struct net_device * ndev)
{
if (!ndev) return;
kfree(ndev->priv);
kfree(ndev->dev_addr);
kfree(ndev);
}
void *__alloc_percpu(size_t size, size_t align)
{
return kmalloc(size, 0);
}
int mii_nway_restart(struct mii_if_info *mii)
{
/* if autoneg is off, it's an error */
int bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR);
if (bmcr & BMCR_ANENABLE) {
printk("Reenable\n");
bmcr |= BMCR_ANRESTART;
mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr);
return 0;
}
return -EINVAL;
}
static net_device * single_net_device = nullptr;
int register_netdev(struct net_device *dev)
{
dev->state |= 1 << __LINK_STATE_START;
int err = dev->netdev_ops->ndo_open(dev);
if (err) return err;
if (dev->netdev_ops->ndo_set_rx_mode)
dev->netdev_ops->ndo_set_rx_mode(dev);
single_net_device = dev;
return 0;
};
void unregister_netdev(struct net_device * dev)
{
if (dev->netdev_ops->ndo_stop)
dev->netdev_ops->ndo_stop(dev);
single_net_device = NULL;
}
net_device *
Linux_network_session_base::
_register_session(Linux_network_session_base &session,
Genode::Session_label policy)
{
if (single_net_device) single_net_device->session_component = &session;
return single_net_device;
}
void tasklet_schedule(struct tasklet_struct *t)
{
Lx::Work *lx_work = (Lx::Work *)tasklet_wq->task;
lx_work->schedule_tasklet(t);
lx_work->unblock();
}
struct workqueue_struct *create_singlethread_workqueue(char const *name)
{
workqueue_struct *wq = (workqueue_struct *)kzalloc(sizeof(workqueue_struct), 0);
Lx::Work *work = Lx::Work::alloc_work_queue(&Lx::Malloc::mem(), name);
wq->task = (void *)work;
return wq;
}
struct workqueue_struct *alloc_workqueue(const char *fmt, unsigned int flags,
int max_active, ...)
{
return create_singlethread_workqueue(fmt);
}
int dev_set_drvdata(struct device *dev, void *data)
{
dev->driver_data = data;
return 0;
}
void * dev_get_drvdata(const struct device *dev)
{
return dev->driver_data;
}
int netif_running(const struct net_device *dev)
{
return dev->state & (1 << __LINK_STATE_START);
}
void netif_carrier_off(struct net_device *dev)
{
dev->state |= 1 << __LINK_STATE_NOCARRIER;
if (dev->session_component)
reinterpret_cast<Linux_network_session_base*>(dev->session_component)->
link_state(false);
}
int netif_carrier_ok(const struct net_device *dev)
{
return !(dev->state & (1 << __LINK_STATE_NOCARRIER));
}
void *kmem_cache_alloc_node(struct kmem_cache *cache, gfp_t gfp_flags, int arg)
{
return (void*)cache->alloc_element();
}
int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd)
{
ecmd->duplex = DUPLEX_FULL;
return 0;
}
void netif_carrier_on(struct net_device *dev)
{
dev->state &= ~(1 << __LINK_STATE_NOCARRIER);
if (dev->session_component)
reinterpret_cast<Linux_network_session_base*>(dev->session_component)->
link_state(true);
}
int netif_rx(struct sk_buff * skb)
{
if (skb->dev->session_component)
reinterpret_cast<Linux_network_session_base*>(skb->dev->session_component)->
receive(skb);
dev_kfree_skb(skb);
return NET_RX_SUCCESS;
}
void dev_kfree_skb_any(struct sk_buff *skb)
{
dev_kfree_skb(skb);
}
int is_valid_ether_addr(const u8 * a)
{
for (unsigned i = 0; i < ETH_ALEN; i++)
if (a[i] != 0 && a[i] != 255) return 1;
return 0;
}
unsigned int mii_check_media (struct mii_if_info *mii, unsigned int ok_to_print, unsigned int init_media)
{
if (mii_link_ok(mii)) netif_carrier_on(mii->dev);
else netif_carrier_off(mii->dev);
return 0;
}
int mii_link_ok (struct mii_if_info *mii)
{
/* first, a dummy read, needed to latch some MII phys */
mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR);
if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS)
return 1;
return 0;
}
static struct page *allocate_pages(gfp_t gfp_mask, unsigned int size)
{
struct page *page = (struct page *)kzalloc(sizeof(struct page), 0);
page->addr = Lx::Malloc::dma().alloc_large(size);
page->size = size;
if (!page->addr) {
Genode::error("alloc_pages: ", size, " failed");
kfree(page);
return 0;
}
Addr_to_page_mapping::insert(page);
atomic_set(&page->_count, 1);
return page;
}
void *page_frag_alloc(struct page_frag_cache *nc, unsigned int fragsz, gfp_t gfp_mask)
{
struct page *page = allocate_pages(gfp_mask, fragsz);
if (!page) return nullptr;
return page->addr;
}
void page_frag_free(void *addr)
{
struct page *page = Addr_to_page_mapping::remove((unsigned long)addr);
if (!atomic_dec_and_test(&page->_count))
Genode::error("page reference count != 0");
Lx::Malloc::dma().free_large(page->addr);
kfree(page);
}

File diff suppressed because it is too large Load Diff

View File

@ -1,424 +0,0 @@
/*
* \brief Linux emulation code
* \author Josef Soentgen
* \date 2014-03-07
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
/* linux includes */
#include <lx_emul.h>
#include <linux/ctype.h>
#include <linux/nls.h>
#include <linux/skbuff.h>
#include <linux/usb.h>
#include <linux/usb/ch9.h>
#include <linux/usb/cdc.h>
#include <linux/usb/quirks.h>
/* local includes */
#include <lxc.h>
struct Skb skb_helper(struct sk_buff *skb)
{
struct Skb helper;
skb_push(skb, ETH_HLEN);
helper.packet = skb->data;
helper.packet_size = skb->len;
helper.frag = 0;
helper.frag_size = 0;
/**
* If received packets are too large (as of now 128 bytes) the actually
* payload is put into a fragment. Otherwise the payload is stored directly
* in the sk_buff.
*/
if (skb_shinfo(skb)->nr_frags) {
if (skb_shinfo(skb)->nr_frags > 1)
printk("more than 1 fragment in skb: %p nr_frags: %d", skb,
skb_shinfo(skb)->nr_frags);
skb_frag_t *f = &skb_shinfo(skb)->frags[0];
helper.frag = skb_frag_address(f);
helper.frag_size = skb_frag_size(f);
/* fragment contains payload but header is still found in packet */
helper.packet_size = ETH_HLEN;
}
return helper;
}
struct sk_buff *lxc_alloc_skb(size_t len, size_t headroom)
{
struct sk_buff *skb = alloc_skb(len + headroom, GFP_KERNEL | GFP_LX_DMA);
skb_reserve(skb, headroom);
return skb;
}
unsigned char *lxc_skb_put(struct sk_buff *skb, size_t len)
{
return skb_put(skb, len);
}
/**
* cdc_parse_cdc_header - parse the extra headers present in CDC devices
* @hdr: the place to put the results of the parsing
* @intf: the interface for which parsing is requested
* @buffer: pointer to the extra headers to be parsed
* @buflen: length of the extra headers
*
* This evaluates the extra headers present in CDC devices which
* bind the interfaces for data and control and provide details
* about the capabilities of the device.
*
* Return: number of descriptors parsed or -EINVAL
* if the header is contradictory beyond salvage
*/
int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr,
struct usb_interface *intf,
u8 *buffer,
int buflen)
{
/* duplicates are ignored */
struct usb_cdc_union_desc *union_header = NULL;
/* duplicates are not tolerated */
struct usb_cdc_header_desc *header = NULL;
struct usb_cdc_ether_desc *ether = NULL;
struct usb_cdc_mdlm_detail_desc *detail = NULL;
struct usb_cdc_mdlm_desc *desc = NULL;
unsigned int elength;
int cnt = 0;
memset(hdr, 0x00, sizeof(struct usb_cdc_parsed_header));
hdr->phonet_magic_present = false;
while (buflen > 0) {
elength = buffer[0];
if (!elength) {
dev_err(&intf->dev, "skipping garbage byte\n");
elength = 1;
goto next_desc;
}
if ((buflen < elength) || (elength < 3)) {
dev_err(&intf->dev, "invalid descriptor buffer length\n");
break;
}
if (buffer[1] != USB_DT_CS_INTERFACE) {
dev_err(&intf->dev, "skipping garbage\n");
goto next_desc;
}
switch (buffer[2]) {
case USB_CDC_UNION_TYPE: /* we've found it */
if (elength < sizeof(struct usb_cdc_union_desc))
goto next_desc;
if (union_header) {
dev_err(&intf->dev, "More than one union descriptor, skipping ...\n");
goto next_desc;
}
union_header = (struct usb_cdc_union_desc *)buffer;
break;
case USB_CDC_COUNTRY_TYPE:
if (elength < sizeof(struct usb_cdc_country_functional_desc))
goto next_desc;
hdr->usb_cdc_country_functional_desc =
(struct usb_cdc_country_functional_desc *)buffer;
break;
case USB_CDC_HEADER_TYPE:
if (elength != sizeof(struct usb_cdc_header_desc))
goto next_desc;
if (header)
return -EINVAL;
header = (struct usb_cdc_header_desc *)buffer;
break;
case USB_CDC_ACM_TYPE:
if (elength < sizeof(struct usb_cdc_acm_descriptor))
goto next_desc;
hdr->usb_cdc_acm_descriptor =
(struct usb_cdc_acm_descriptor *)buffer;
break;
case USB_CDC_ETHERNET_TYPE:
if (elength != sizeof(struct usb_cdc_ether_desc))
goto next_desc;
if (ether)
return -EINVAL;
ether = (struct usb_cdc_ether_desc *)buffer;
break;
case USB_CDC_CALL_MANAGEMENT_TYPE:
if (elength < sizeof(struct usb_cdc_call_mgmt_descriptor))
goto next_desc;
hdr->usb_cdc_call_mgmt_descriptor =
(struct usb_cdc_call_mgmt_descriptor *)buffer;
break;
case USB_CDC_DMM_TYPE:
if (elength < sizeof(struct usb_cdc_dmm_desc))
goto next_desc;
hdr->usb_cdc_dmm_desc =
(struct usb_cdc_dmm_desc *)buffer;
break;
case USB_CDC_MDLM_TYPE:
if (elength < sizeof(struct usb_cdc_mdlm_desc *))
goto next_desc;
if (desc)
return -EINVAL;
desc = (struct usb_cdc_mdlm_desc *)buffer;
break;
case USB_CDC_MDLM_DETAIL_TYPE:
if (elength < sizeof(struct usb_cdc_mdlm_detail_desc *))
goto next_desc;
if (detail)
return -EINVAL;
detail = (struct usb_cdc_mdlm_detail_desc *)buffer;
break;
case USB_CDC_NCM_TYPE:
if (elength < sizeof(struct usb_cdc_ncm_desc))
goto next_desc;
hdr->usb_cdc_ncm_desc = (struct usb_cdc_ncm_desc *)buffer;
break;
case USB_CDC_MBIM_TYPE:
if (elength < sizeof(struct usb_cdc_mbim_desc))
goto next_desc;
hdr->usb_cdc_mbim_desc = (struct usb_cdc_mbim_desc *)buffer;
break;
case USB_CDC_MBIM_EXTENDED_TYPE:
if (elength < sizeof(struct usb_cdc_mbim_extended_desc))
break;
hdr->usb_cdc_mbim_extended_desc =
(struct usb_cdc_mbim_extended_desc *)buffer;
break;
case CDC_PHONET_MAGIC_NUMBER:
hdr->phonet_magic_present = true;
break;
default:
/*
* there are LOTS more CDC descriptors that
* could legitimately be found here.
*/
dev_dbg(&intf->dev, "Ignoring descriptor: type %02x, length %ud\n",
buffer[2], elength);
goto next_desc;
}
cnt++;
next_desc:
buflen -= elength;
buffer += elength;
}
hdr->usb_cdc_union_desc = union_header;
hdr->usb_cdc_header_desc = header;
hdr->usb_cdc_mdlm_detail_desc = detail;
hdr->usb_cdc_mdlm_desc = desc;
hdr->usb_cdc_ether_desc = ether;
return cnt;
}
EXPORT_SYMBOL(cdc_parse_cdc_header);
struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev,
unsigned ifnum)
{
struct usb_host_config *config = dev->actconfig;
int i;
if (!config) {
lx_printf("No config for %u\n", ifnum);
return NULL;
}
for (i = 0; i < config->desc.bNumInterfaces; i++) {
if (config->interface[i]->altsetting[0]
.desc.bInterfaceNumber == ifnum) {
return config->interface[i];
}
}
lx_printf("No interface for %u\n");
return NULL;
}
static int usb_get_string(struct usb_device *dev, unsigned short langid,
unsigned char index, void *buf, int size)
{
int i;
int result;
if (size <= 0) /* No point in asking for no data */
return -EINVAL;
for (i = 0; i < 3; ++i) {
/* retry on length 0 or stall; some devices are flakey */
result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
(USB_DT_STRING << 8) + index, langid, buf, size,
USB_CTRL_GET_TIMEOUT);
if (result == 0 || result == -EPIPE)
continue;
if (result > 1 && ((u8 *) buf)[1] != USB_DT_STRING) {
result = -ENODATA;
continue;
}
break;
}
return result;
}
static void usb_try_string_workarounds(unsigned char *buf, int *length)
{
int newlength, oldlength = *length;
for (newlength = 2; newlength + 1 < oldlength; newlength += 2)
if (!isprint(buf[newlength]) || buf[newlength + 1])
break;
if (newlength > 2) {
buf[0] = newlength;
*length = newlength;
}
}
static int usb_string_sub(struct usb_device *dev, unsigned int langid,
unsigned int index, unsigned char *buf)
{
int rc;
/* Try to read the string descriptor by asking for the maximum
* possible number of bytes */
if (dev->quirks & USB_QUIRK_STRING_FETCH_255)
rc = -EIO;
else
rc = usb_get_string(dev, langid, index, buf, 255);
/* If that failed try to read the descriptor length, then
* ask for just that many bytes */
if (rc < 2) {
rc = usb_get_string(dev, langid, index, buf, 2);
if (rc == 2)
rc = usb_get_string(dev, langid, index, buf, buf[0]);
}
if (rc >= 2) {
if (!buf[0] && !buf[1])
usb_try_string_workarounds(buf, &rc);
/* There might be extra junk at the end of the descriptor */
if (buf[0] < rc)
rc = buf[0];
rc = rc - (rc & 1); /* force a multiple of two */
}
if (rc < 2)
rc = (rc < 0 ? rc : -EINVAL);
return rc;
}
static int usb_get_langid(struct usb_device *dev, unsigned char *tbuf)
{
int err;
if (dev->have_langid)
return 0;
if (dev->string_langid < 0)
return -EPIPE;
err = usb_string_sub(dev, 0, 0, tbuf);
/* If the string was reported but is malformed, default to english
* (0x0409) */
if (err == -ENODATA || (err > 0 && err < 4)) {
dev->string_langid = 0x0409;
dev->have_langid = 1;
dev_err(&dev->dev,
"language id specifier not provided by device, defaulting to English\n");
return 0;
}
/* In case of all other errors, we assume the device is not able to
* deal with strings at all. Set string_langid to -1 in order to
* prevent any string to be retrieved from the device */
if (err < 0) {
dev_info(&dev->dev, "string descriptor 0 read error: %d\n",
err);
dev->string_langid = -1;
return -EPIPE;
}
/* always use the first langid listed */
dev->string_langid = tbuf[2] | (tbuf[3] << 8);
dev->have_langid = 1;
dev_dbg(&dev->dev, "default language 0x%04x\n",
dev->string_langid);
return 0;
}
/**
* usb_string - returns UTF-8 version of a string descriptor
* @dev: the device whose string descriptor is being retrieved
* @index: the number of the descriptor
* @buf: where to put the string
* @size: how big is "buf"?
* Context: !in_interrupt ()
*
* This converts the UTF-16LE encoded strings returned by devices, from
* usb_get_string_descriptor(), to null-terminated UTF-8 encoded ones
* that are more usable in most kernel contexts. Note that this function
* chooses strings in the first language supported by the device.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Return: length of the string (>= 0) or usb_control_msg status (< 0).
*/
int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
{
unsigned char *tbuf;
int err;
if (dev->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
if (size <= 0 || !buf || !index)
return -EINVAL;
buf[0] = 0;
tbuf = kmalloc(256, GFP_NOIO);
if (!tbuf)
return -ENOMEM;
err = usb_get_langid(dev, tbuf);
if (err < 0)
goto errout;
err = usb_string_sub(dev, dev->string_langid, index, tbuf);
if (err < 0)
goto errout;
size--; /* leave room for trailing NULL char in output buffer */
err = utf16s_to_utf8s((wchar_t *) &tbuf[2], (err - 2) / 2,
UTF16_LITTLE_ENDIAN, buf, size);
buf[err] = 0;
if (tbuf[1] != USB_DT_STRING)
dev_dbg(&dev->dev,
"wrong descriptor type %02x for string %d (\"%s\")\n",
tbuf[1], index, buf);
errout:
kfree(tbuf);
return err;
}
EXPORT_SYMBOL_GPL(usb_string);

View File

@ -1,40 +0,0 @@
/*
* \brief Lx C env
* \author Josef Soentgen
* \date 2016-03-04
*/
/*
* Copyright (C) 2016-2017 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#ifndef _LXC_H_
#define _LXC_H_
/*
* The sk_buff struct contains empty array members whose
* size differs between C and C++. Since we want to access
* certain members of the sk_buff from C++ we have to use
* a uniform format useable from both languages.W
*
* Note: we pull struct skb_buff as well as size_t from
* headers included before this one.
*/
struct Skb
{
void *packet;
size_t packet_size;
void *frag;
size_t frag_size;
};
struct Skb skb_helper(struct sk_buff *skb);
bool is_eapol(struct sk_buff *skb);
struct sk_buff *lxc_alloc_skb(size_t len, size_t headroom);
unsigned char *lxc_skb_put(struct sk_buff *skb, size_t len);
#endif /* _LXC_H_ */

View File

@ -1,235 +0,0 @@
/*
* \brief USB net driver
* \author Stefan Kalkowski
* \date 2018-06-07
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/component.h>
#include <driver.h>
#include <lx_emul.h>
#include <legacy/lx_kit/env.h>
#include <legacy/lx_kit/malloc.h>
#include <legacy/lx_kit/scheduler.h>
#include <legacy/lx_kit/timer.h>
#include <legacy/lx_kit/work.h>
#include <legacy/lx_emul/extern_c_begin.h>
#include <linux/usb.h>
#include <legacy/lx_emul/extern_c_end.h>
struct workqueue_struct *tasklet_wq;
void Driver::Device::scan_altsettings(usb_interface * iface,
unsigned iface_idx, unsigned alt_idx)
{
Usb::Interface_descriptor iface_desc;
usb.interface_descriptor(iface_idx, alt_idx, &iface_desc);
Genode::memcpy(&iface->altsetting[alt_idx].desc, &iface_desc,
sizeof(usb_interface_descriptor));
if (iface_desc.active)
iface->cur_altsetting = &iface->altsetting[alt_idx];
Usb::Interface_extra iface_extra;
if (usb.interface_extra(iface_idx, alt_idx, &iface_extra)) {
iface->altsetting[alt_idx].extra = (unsigned char *)kzalloc(iface_extra.length, 0);
Genode::memcpy(iface->altsetting[alt_idx].extra, iface_extra.data,
iface_extra.length);
iface->altsetting[alt_idx].extralen = iface_extra.length;
}
iface->altsetting[alt_idx].endpoint = (usb_host_endpoint*)
kzalloc(sizeof(usb_host_endpoint)*iface->altsetting[alt_idx].desc.bNumEndpoints, GFP_KERNEL);
for (unsigned i = 0; i < iface->altsetting[alt_idx].desc.bNumEndpoints; i++) {
Usb::Endpoint_descriptor ep_desc[7];
usb.endpoint_descriptor(iface_idx, alt_idx, i, ep_desc);
Genode::memcpy(&iface->altsetting[alt_idx].endpoint[i].desc,
ep_desc, sizeof(usb_endpoint_descriptor));
int epnum = usb_endpoint_num(&iface->altsetting[alt_idx].endpoint[i].desc);
if (usb_endpoint_dir_out(&iface->altsetting[alt_idx].endpoint[i].desc))
udev->ep_out[epnum] = &iface->altsetting[alt_idx].endpoint[i];
else
udev->ep_in[epnum] = &iface->altsetting[alt_idx].endpoint[i];
}
}
void Driver::Device::scan_interfaces(unsigned iface_idx)
{
struct usb_interface * iface =
(usb_interface*) kzalloc(sizeof(usb_interface), GFP_KERNEL);
iface->num_altsetting = usb.alt_settings(iface_idx);
iface->altsetting = (usb_host_interface*)
kzalloc(sizeof(usb_host_interface)*iface->num_altsetting, GFP_KERNEL);
iface->dev.parent = &udev->dev;
iface->dev.bus = (bus_type*) 0xdeadbeef;
for (unsigned i = 0; i < iface->num_altsetting; i++)
scan_altsettings(iface, iface_idx, i);
udev->config->interface[iface_idx] = iface;
};
void Driver::Device::register_device()
{
if (udev) {
Genode::error("device already registered!");
return;
}
Usb::Device_descriptor dev_desc;
Usb::Config_descriptor config_desc;
usb.config_descriptor(&dev_desc, &config_desc);
udev = (usb_device*) kzalloc(sizeof(usb_device), GFP_KERNEL);
udev->bus = (usb_bus*) kzalloc(sizeof(usb_bus), GFP_KERNEL);
udev->config = (usb_host_config*) kzalloc(sizeof(usb_host_config), GFP_KERNEL);
udev->bus->bus_name = "usbbus";
udev->bus->controller = (device*) (&usb);
udev->descriptor.idVendor = dev_desc.vendor_id;
udev->descriptor.idProduct = dev_desc.product_id;
udev->descriptor.bcdDevice = dev_desc.device_release;
for (unsigned i = 0; i < config_desc.num_interfaces; i++)
scan_interfaces(i);
udev->actconfig = udev->config;
udev->config->desc.bNumInterfaces = config_desc.num_interfaces;
/* probe */
for (unsigned i = 0; i < config_desc.num_interfaces; i++) {
struct usb_device_id id;
probe_interface(udev->config->interface[i], &id);
}
driver.activate_network_session();
}
void Driver::Device::unregister_device()
{
for (unsigned i = 0; i < USB_MAXINTERFACES; i++) {
if (!udev->config->interface[i]) break;
else remove_interface(udev->config->interface[i]);
}
kfree(udev->bus);
kfree(udev->config);
kfree(udev);
udev = nullptr;
}
void Driver::Device::state_task_entry(void * arg)
{
Device & dev = *reinterpret_cast<Device*>(arg);
for (;;) {
if (dev.usb.plugged() && !dev.udev)
dev.register_device();
if (!dev.usb.plugged() && dev.udev)
dev.unregister_device();
Lx::scheduler().current()->block_and_schedule();
}
}
void Driver::Device::urb_task_entry(void * arg)
{
Device & dev = *reinterpret_cast<Device*>(arg);
for (;;) {
while (dev.udev && dev.usb.source()->ack_avail()) {
Usb::Packet_descriptor p = dev.usb.source()->get_acked_packet();
if (p.completion) p.completion->complete(p);
dev.usb.source()->release_packet(p);
}
Lx::scheduler().current()->block_and_schedule();
}
}
Driver::Device::Device(Driver & driver, Label label)
: label(label),
driver(driver),
env(driver.env),
alloc(driver.alloc),
state_task(env.ep(), state_task_entry, reinterpret_cast<void*>(this),
"usb_state", Lx::Task::PRIORITY_0, Lx::scheduler()),
urb_task(env.ep(), urb_task_entry, reinterpret_cast<void*>(this),
"usb_urb", Lx::Task::PRIORITY_0, Lx::scheduler())
{
usb.tx_channel()->sigh_ack_avail(urb_task.handler);
driver.devices.insert(&le);
}
Driver::Device::~Device()
{
driver.devices.remove(&le);
if (udev) unregister_device();
while (usb.source()->ack_avail()) {
Usb::Packet_descriptor p = usb.source()->get_acked_packet();
usb.source()->release_packet(p);
}
}
void Driver::main_task_entry(void * arg)
{
Driver * driver = reinterpret_cast<Driver*>(arg);
tasklet_wq = alloc_workqueue("tasklet_wq", 0, 0);
skb_init();
module_usbnet_init();
module_smsc95xx_driver_init();
module_asix_driver_init();
module_ax88179_178a_driver_init();
module_cdc_driver_init();
module_rndis_driver_init();
static Device dev(*driver, Label(""));
for (;;) Lx::scheduler().current()->block_and_schedule();
}
Driver::Driver(Genode::Env &env) : env(env)
{
Genode::log("--- USB net driver ---");
Lx_kit::construct_env(env);
Lx::scheduler(&env);
Lx::malloc_init(env, heap);
Lx::timer(&env, &ep, &heap, &jiffies);
Lx::Work::work_queue(&heap);
main_task.construct(env.ep(), main_task_entry, reinterpret_cast<void*>(this),
"main", Lx::Task::PRIORITY_0, Lx::scheduler());
/* give all task a first kick before returning */
Lx::scheduler().schedule();
}
void Component::construct(Genode::Env &env)
{
env.exec_static_constructors();
static Driver driver(env);
}

View File

@ -1,40 +0,0 @@
TARGET := usb_net_drv
SRC_C := dummies.c lxc.c
SRC_CC := main.cc lx_emul.cc linux_network_session_base.cc
SRC_CC += printf.cc bug.cc timer.cc scheduler.cc malloc.cc env.cc work.cc
SRC_CC += uplink_client.cc
LIBS := base usb_net_include lx_kit_setjmp nic_driver format
USB_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_net
INC_DIR += $(PRG_DIR)
INC_DIR += $(REP_DIR)/src/include
INC_DIR += $(REP_DIR)/src/drivers/nic
SRC_C += drivers/net/usb/asix_common.c
SRC_C += drivers/net/usb/asix_devices.c
SRC_C += drivers/net/usb/ax88172a.c
SRC_C += drivers/net/usb/ax88179_178a.c
SRC_C += drivers/net/usb/cdc_ether.c
SRC_C += drivers/net/usb/rndis_host.c
SRC_C += drivers/net/usb/smsc95xx.c
SRC_C += drivers/net/usb/usbnet.c
SRC_C += fs/nls/nls_base.c
SRC_C += lib/ctype.c
SRC_C += lib/hexdump.c
SRC_C += net/core/skbuff.c
SRC_C += net/ethernet/eth.c
CC_OPT += -Wno-address-of-packed-member
CC_C_OPT += -Wno-comment -Wno-int-conversion -Wno-incompatible-pointer-types \
-Wno-unused-variable -Wno-pointer-sign -Wno-uninitialized \
-Wno-maybe-uninitialized -Wno-format -Wno-discarded-qualifiers \
-Wno-unused-function -Wno-unused-but-set-variable
CC_CXX_WARN_STRICT =
vpath linux_network_session_base.cc $(REP_DIR)/src/drivers/nic
vpath %.c $(USB_CONTRIB_DIR)
vpath %.cc $(REP_DIR)/src/lib/legacy/lx_kit

View File

@ -1,93 +0,0 @@
/*
* \brief Uplink session client role of the driver
* \author Martin Stein
* \date 2020-12-10
*/
/*
* Copyright (C) 2020 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* local include */
#include <uplink_client.h>
#include <lx_emul.h>
extern "C" {
#include <lxc.h>
};
Genode::Uplink_client::Transmit_result
Genode::Uplink_client::_drv_transmit_pkt(const char *conn_rx_pkt_base,
size_t conn_rx_pkt_size)
{
/*
* We must not be called from another task, just from the
* packet stream dispatcher.
*/
if (Lx::scheduler().active()) {
warning("scheduler active");
return Transmit_result::RETRY;
}
struct sk_buff *skb {
lxc_alloc_skb(conn_rx_pkt_size +
HEAD_ROOM, HEAD_ROOM) };
unsigned char *data = lxc_skb_put(skb, conn_rx_pkt_size);
memcpy(data, conn_rx_pkt_base, conn_rx_pkt_size);
_tx_data.ndev = _ndev;
_tx_data.skb = skb;
_tx_task.unblock();
Lx::scheduler().schedule();
return Transmit_result::ACCEPTED;
}
Genode::Uplink_client::Uplink_client(Env &env,
Allocator &alloc,
Session_label const &label)
:
Linux_network_session_base { label },
Uplink_client_base { env, alloc,
Net::Mac_address(_ndev->dev_addr) }
{
_drv_handle_link_state(_read_link_state_from_ndev());
}
void Genode::Uplink_client::link_state(bool state)
{
_drv_handle_link_state(state);
}
void Genode::Uplink_client::receive(struct sk_buff *skb)
{
Skb skb_helpr { skb_helper(skb) };
_drv_rx_handle_pkt(
skb_helpr.packet_size + skb_helpr.frag_size,
[&] (void *conn_tx_pkt_base,
size_t &)
{
memcpy(
conn_tx_pkt_base,
skb_helpr.packet,
skb_helpr.packet_size);
if (skb_helpr.frag_size) {
memcpy(
(char *)conn_tx_pkt_base + skb_helpr.packet_size,
skb_helpr.frag,
skb_helpr.frag_size);
}
return Write_result::WRITE_SUCCEEDED;
});
}

View File

@ -1,58 +0,0 @@
/*
* \brief Uplink session client role of the driver
* \author Martin Stein
* \date 2020-12-10
*/
/*
* Copyright (C) 2020 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__DRIVERS__NIC__FEC__UPLINK_CLIENT_H_
#define _SRC__DRIVERS__NIC__FEC__UPLINK_CLIENT_H_
/* NIC driver includes */
#include <drivers/nic/uplink_client_base.h>
/* local include */
#include <linux_network_session_base.h>
namespace Genode {
class Uplink_client;
}
class Genode::Uplink_client : public Linux_network_session_base,
public Uplink_client_base
{
private:
/************************
** Uplink_client_base **
************************/
Transmit_result
_drv_transmit_pkt(const char *conn_rx_pkt_base,
size_t conn_rx_pkt_size) override;
public:
Uplink_client(Env &env,
Allocator &alloc,
Session_label const &label);
/********************************
** Linux_network_session_base **
********************************/
void link_state(bool state) override;
void receive(struct sk_buff *skb) override;
};
#endif /* _SRC__DRIVERS__NIC__FEC__UPLINK_CLIENT_H_ */