mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-29 15:44:02 +00:00
parent
cd2910eb2c
commit
7e823f7c19
@ -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
|
@ -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 =
|
@ -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" ) > $@
|
@ -1 +0,0 @@
|
||||
2023-08-21 1a1be9d8df290e48fdb5539bef1c23367b596955
|
@ -1,8 +0,0 @@
|
||||
base
|
||||
os
|
||||
format
|
||||
nic_session
|
||||
uplink_session
|
||||
usb_session
|
||||
timer_session
|
||||
nic_driver
|
@ -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 \
|
||||
|
@ -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.
|
||||
|
@ -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_ */
|
@ -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;
|
@ -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
@ -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);
|
||||
|
@ -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_ */
|
@ -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);
|
||||
}
|
@ -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
|
@ -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;
|
||||
});
|
||||
}
|
@ -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_ */
|
Loading…
x
Reference in New Issue
Block a user