mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
dde_linux: remove usb_modem driver
The driver is superseded by the USB network driver (usb_net) which also contains MBIM support for LTE modems previously provided by this driver. issue #4958
This commit is contained in:
parent
7e823f7c19
commit
798fb709a2
@ -1,11 +0,0 @@
|
||||
USB_MODEM_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_modem
|
||||
|
||||
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_MODEM_CONTRIB_DIR)/include
|
||||
INC_DIR += $(LIB_CACHE_DIR)/usb_modem_include/include/include/include
|
@ -1,37 +0,0 @@
|
||||
ifeq ($(called_from_lib_mk),yes)
|
||||
|
||||
USB_MODEM_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_modem
|
||||
LX_EMUL_H := $(REP_DIR)/src/drivers/usb_modem/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_MODEM_CONTRIB_DIR)/include/, asm-generic linux uapi net) \
|
||||
$(addprefix $(USB_MODEM_CONTRIB_DIR)/, drivers net)
|
||||
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_MODEM_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,2 +0,0 @@
|
||||
|
||||
Runtime for USB GSM/LTE modem driver
|
@ -1 +0,0 @@
|
||||
_/src/usb_modem_drv
|
@ -1 +0,0 @@
|
||||
2023-08-21 9f84b33811807c30d1f3ad65d80934aeb95c8f46
|
@ -1,12 +0,0 @@
|
||||
<runtime ram="16M" caps="300" binary="usb_modem_drv">
|
||||
|
||||
<requires> <uplink/> <usb/> <rm/> </requires>
|
||||
<provides> <terminal/> </provides>
|
||||
|
||||
<config mac="02:00:00:00:01:01"/>
|
||||
|
||||
<content>
|
||||
<rom label="ld.lib.so"/>
|
||||
<rom label="usb_modem_drv"/>
|
||||
</content>
|
||||
</runtime>
|
@ -1,36 +0,0 @@
|
||||
PORT_DIR := $(call port_dir,$(REP_DIR)/ports/dde_linux)
|
||||
|
||||
MIRROR_FROM_REP_DIR := src/drivers/usb_modem \
|
||||
src/lib/legacy/lx_kit \
|
||||
src/lib/lx_kit/spec \
|
||||
src/include/legacy \
|
||||
lib/import/import-usb_modem_include.mk \
|
||||
lib/import/import-usb_arch_include.mk \
|
||||
lib/mk/usb_modem_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_modem -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 dd458cda686faf044323cbf00decbfc452b1799c
|
@ -1,9 +0,0 @@
|
||||
base
|
||||
os
|
||||
format
|
||||
nic_session
|
||||
uplink_session
|
||||
usb_session
|
||||
timer_session
|
||||
terminal_session
|
||||
nic_driver
|
@ -1,33 +0,0 @@
|
||||
USB GSM modem driver
|
||||
####################
|
||||
|
||||
Driver for GSM modem cards connected via USB/M.2
|
||||
|
||||
Currently there is support for MBIM (Mobile Broadband Interface Model) devices
|
||||
only. QMI devices might be supported in the future.
|
||||
|
||||
Tested devices:
|
||||
Huawai ME906s (P/V: 12d1:15c1)
|
||||
Fibocom L830-EB-00 (P/V: 2cb7:0210)
|
||||
|
||||
Other devices can be added by enabling the MBIM configuration profile for the
|
||||
USB device in ' Driver::Device::set_config' (main.cc) of this driver.
|
||||
|
||||
Configuration snippet:
|
||||
|
||||
!<start name="usb_modem_drv">
|
||||
! <resource name="RAM" quantum="10M"/>
|
||||
! <requires>
|
||||
! <service name="Uplink"/>
|
||||
! </requires>
|
||||
! <provides>
|
||||
! <service name="Terminal"/>
|
||||
! </provides>
|
||||
! <config mac="02:00:00:00:01:01"/>
|
||||
!</start>
|
||||
|
||||
The driver offers two Genode sessions: The first one is a terminal session where
|
||||
raw packet data, for example, MBIM packets can be send to the device via CDC WDM
|
||||
(wireless communication device class). An example can be found in Genode World
|
||||
(_src/app/mbimcli_). Once a data connection is established via the Terminal
|
||||
session, the Uplink session can be used to transfer Ethernet frames.
|
@ -1,175 +0,0 @@
|
||||
/*
|
||||
* \brief USB net driver
|
||||
* \author Stefan Kalkowski
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2018-06-27
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018-2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SRC__DRIVERS__USB_MODEM__DRIVER_H_
|
||||
#define _SRC__DRIVERS__USB_MODEM__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>
|
||||
#include <terminal.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 *);
|
||||
void set_config(Usb::Device_descriptor const &desc);
|
||||
};
|
||||
|
||||
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 { };
|
||||
Terminal::Root terminal_root { env, heap };
|
||||
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,624 +0,0 @@
|
||||
/*
|
||||
* \brief Dummies
|
||||
* \author Stefan Kalkowski
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2020-12-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <lx_emul.h>
|
||||
|
||||
#if 0
|
||||
#define TRACE \
|
||||
do { \
|
||||
lx_printf("%s not implemented from %p\n", __func__, __builtin_return_address(0)); \
|
||||
} while (0)
|
||||
#else
|
||||
#define TRACE do { ; } while (0)
|
||||
#endif
|
||||
|
||||
#define TRACE_AND_STOP \
|
||||
do { \
|
||||
lx_printf("%s not implemented from %p\n", __func__, __builtin_return_address(0)); \
|
||||
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;
|
||||
}
|
||||
|
||||
void dev_hold(struct net_device *dev)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
}
|
||||
|
||||
void dev_put(struct net_device *dev)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
}
|
||||
|
||||
const char *dev_name(const struct device *dev)
|
||||
{
|
||||
TRACE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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_netdev(struct net_device * ndev)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
}
|
||||
|
||||
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 hex2bin(u8 *dst, const char *src, size_t count)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void netif_tx_lock_bh(struct net_device *dev)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
void netif_tx_unlock_bh(struct net_device *dev)
|
||||
{
|
||||
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 unregister_netdev(struct net_device * dev)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
}
|
||||
|
||||
void secpath_reset(struct sk_buff * skb)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
void __set_current_state(int state)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
}
|
||||
|
||||
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(spinlock_t *lock)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
void spin_lock_irq(spinlock_t *lock)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
void spin_lock_nested(spinlock_t *lock, int subclass)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
void spin_unlock_irq(spinlock_t *lock)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
void spin_lock_bh(spinlock_t *lock)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
void spin_unlock_bh(spinlock_t *lock)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
size_t strlcpy(char *dest, const char *src, size_t size)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void tasklet_kill(struct tasklet_struct *t)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
}
|
||||
|
||||
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_AND_STOP;
|
||||
}
|
||||
|
||||
struct usb_anchor;
|
||||
struct urb *usb_get_from_anchor(struct usb_anchor *anchor)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct urb *usb_get_urb(struct urb *urb)
|
||||
{
|
||||
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_AND_STOP;
|
||||
}
|
||||
|
||||
int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
const struct usb_device_id *usb_match_id(struct usb_interface *interface,
|
||||
const struct usb_device_id *id)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct usb_host_interface *usb_altnum_to_altsetting(
|
||||
const struct usb_interface *intf, unsigned int altnum)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ktime_t ktime_get_real(void)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void kunmap_atomic(void *addr)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
}
|
||||
|
||||
int kstrtoul(const char *s, unsigned int base, unsigned long *res)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void usb_kill_urb(struct urb *urb)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
}
|
||||
|
||||
int usb_unlink_urb(struct urb *urb)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
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 __vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
|
||||
{
|
||||
TRACE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void __vlan_hwaccel_put_tag(struct sk_buff *skb, __be16 vlan_proto, u16 vlan_tci)
|
||||
{
|
||||
TRACE;
|
||||
}
|
||||
|
||||
struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct net_device *
|
||||
__vlan_find_dev_deep_rcu(struct net_device *real_dev, __be16 vlan_proto, u16 vlan_id)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ipv6_addr_is_solict_mult(const struct in6_addr *addr)
|
||||
{
|
||||
TRACE;
|
||||
return false;
|
||||
}
|
||||
|
||||
int ipv6_addr_type(const struct in6_addr *addr)
|
||||
{
|
||||
TRACE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct inet6_dev *in6_dev_get(const struct net_device *dev)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void in6_dev_put(struct inet6_dev *idev)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
}
|
||||
|
||||
|
||||
struct usb_class_driver;
|
||||
void usb_deregister_dev(struct usb_interface *intf,struct usb_class_driver *class_driver)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
}
|
||||
|
||||
void poll_wait(struct file *f, wait_queue_head_t *w, poll_table *p)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
}
|
||||
|
||||
loff_t noop_llseek(struct file *file, loff_t offset, int whence)
|
||||
{
|
||||
TRACE_AND_STOP;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int sysctl_tstamp_allow_data;
|
||||
struct user_namespace init_user_ns;
|
||||
const struct ipv6_stub *ipv6_stub;
|
@ -1,89 +0,0 @@
|
||||
/*
|
||||
* \brief Virtual interface of a network session connected to the driver
|
||||
* \author Martin Stein
|
||||
* \date 2020-12-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <fec_nic.h>
|
||||
#include <legacy/lx_kit/scheduler.h>
|
||||
#include <lx_emul.h>
|
||||
|
||||
|
||||
void Fec_nic::_run_tx_task(void * args)
|
||||
{
|
||||
Tx_data *data = static_cast<Tx_data*>(args);
|
||||
|
||||
while (1) {
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
|
||||
net_device * ndev = data->ndev;
|
||||
struct sk_buff * skb = data->skb;
|
||||
|
||||
ndev->netdev_ops->ndo_start_xmit(skb, ndev);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Fec_nic::_run_rx_task(void * args)
|
||||
{
|
||||
Rx_data *data = static_cast<Rx_data*>(args);
|
||||
|
||||
while (1) {
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
|
||||
int ret = 0;
|
||||
struct napi_struct * n = data->napi;
|
||||
|
||||
for (;;) {
|
||||
|
||||
/* This NAPI_STATE_SCHED test is for avoiding a race
|
||||
* with netpoll's poll_napi(). Only the entity which
|
||||
* obtains the lock and sees NAPI_STATE_SCHED set will
|
||||
* actually make the ->poll() call. Therefore we avoid
|
||||
* accidentally calling ->poll() when NAPI is not scheduled.
|
||||
*/
|
||||
if (!test_bit(NAPI_STATE_SCHED, &n->state)) break;
|
||||
|
||||
int weight = n->weight;
|
||||
int work = n->poll(n, weight);
|
||||
ret += work;
|
||||
|
||||
if (work < weight) break;
|
||||
|
||||
Genode::warning("Too much incoming traffic, we should "
|
||||
"schedule RX more intelligent");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Fec_nic::Fec_nic(Genode::Session_label const &label)
|
||||
:
|
||||
_ndev { _register_fec_nic(*this, label) }
|
||||
{
|
||||
|
||||
if (!_ndev) {
|
||||
|
||||
throw Genode::Service_denied();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Fec_nic::_read_link_state_from_ndev() const
|
||||
{
|
||||
return !(_ndev->state & (1UL << __LINK_STATE_NOCARRIER));
|
||||
}
|
||||
|
||||
|
||||
void Fec_nic::unblock_rx_task(napi_struct * n)
|
||||
{
|
||||
_rx_data.napi = n;
|
||||
_rx_task.unblock();
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* \brief Virtual interface of a network session connected to the driver
|
||||
* \author Martin Stein
|
||||
* \date 2020-12-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#ifndef _SRC__DRIVERS__NIC__FEC__FEC_NIC_H_
|
||||
#define _SRC__DRIVERS__NIC__FEC__FEC_NIC_H_
|
||||
|
||||
#include <legacy/lx_kit/scheduler.h>
|
||||
|
||||
/* forward declarations */
|
||||
extern "C" {
|
||||
struct net_device;
|
||||
struct napi_struct;
|
||||
struct sk_buff;
|
||||
}
|
||||
|
||||
|
||||
class Fec_nic
|
||||
{
|
||||
protected:
|
||||
|
||||
enum { HEAD_ROOM = 8 };
|
||||
|
||||
struct Tx_data
|
||||
{
|
||||
net_device * ndev;
|
||||
sk_buff * skb;
|
||||
};
|
||||
|
||||
struct Rx_data
|
||||
{
|
||||
struct napi_struct * napi;
|
||||
};
|
||||
|
||||
net_device * _ndev = nullptr;
|
||||
Tx_data _tx_data;
|
||||
Rx_data _rx_data;
|
||||
Lx::Task _tx_task { _run_tx_task, &_tx_data, "tx_task",
|
||||
Lx::Task::PRIORITY_1, Lx::scheduler() };
|
||||
Lx::Task _rx_task { _run_rx_task, &_rx_data, "rx_task",
|
||||
Lx::Task::PRIORITY_1, Lx::scheduler() };
|
||||
|
||||
static void _run_tx_task(void * args);
|
||||
|
||||
static void _run_rx_task(void * args);
|
||||
|
||||
static net_device *_register_fec_nic(Fec_nic &fec_nic,
|
||||
Genode::Session_label label);
|
||||
|
||||
bool _read_link_state_from_ndev() const;
|
||||
|
||||
public:
|
||||
|
||||
Fec_nic(Genode::Session_label const &label);
|
||||
|
||||
void unblock_rx_task(napi_struct * n);
|
||||
|
||||
|
||||
/***********************
|
||||
** Virtual interface **
|
||||
***********************/
|
||||
|
||||
virtual void receive(struct sk_buff *skb) = 0;
|
||||
|
||||
virtual void link_state(bool state) = 0;
|
||||
};
|
||||
|
||||
#endif /* _SRC__DRIVERS__NIC__FEC__FEC_NIC_H_ */
|
@ -1,663 +0,0 @@
|
||||
/*
|
||||
* \brief Linux emulation
|
||||
* \author Stefan Kalkowski
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2020-12-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#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/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 <legacy/lx_emul/impl/kernel.h>
|
||||
|
||||
#include <linux/mii.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;
|
||||
}
|
||||
|
||||
|
||||
int usb_register_dev(struct usb_interface *intf, struct usb_class_driver *class_driver)
|
||||
{
|
||||
usb_device *udev = interface_to_usbdev(intf);
|
||||
if (Genode::strcmp(class_driver->name, "cdc-wdm", 7) == 0) {
|
||||
Terminal::Root *terminal = reinterpret_cast<Terminal::Root *>(udev->bus->sysdev);
|
||||
terminal->class_driver(class_driver);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Genode::error(__func__, " no device for class driver '",
|
||||
(char const*)class_driver->name, "'");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
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 *__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;
|
||||
};
|
||||
|
||||
|
||||
net_device * Fec_nic::_register_fec_nic(Fec_nic &fec_nic,
|
||||
Genode::Session_label policy)
|
||||
{
|
||||
if (single_net_device) single_net_device->session_component = &fec_nic;
|
||||
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<Fec_nic*>(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<Fec_nic*>(dev->session_component)->link_state(true);
|
||||
}
|
||||
|
||||
|
||||
int netif_rx(struct sk_buff * skb)
|
||||
{
|
||||
if (skb->dev->session_component)
|
||||
reinterpret_cast<Fec_nic*>(skb->dev->session_component)->receive(skb);
|
||||
|
||||
dev_kfree_skb(skb);
|
||||
return NET_RX_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
struct sk_buff;
|
||||
void dev_kfree_skb_any(struct sk_buff *skb)
|
||||
{
|
||||
TRACE;
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
unsigned iminor(const struct inode *inode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void *memdup_user(const void *src, size_t len)
|
||||
{
|
||||
void *out = kmalloc(len, 0);
|
||||
memcpy(out, src, len);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
long copy_to_user(void *to, const void *from, unsigned long n)
|
||||
{
|
||||
memcpy(to, from, n);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mutex_lock_interruptible(struct mutex *m)
|
||||
{
|
||||
mutex_lock(m);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode)
|
||||
{
|
||||
hrtimer_start_range_ns(timer, tim, 0, mode);
|
||||
}
|
||||
|
||||
|
||||
int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
|
||||
{
|
||||
TRACE;
|
||||
*vlan_tci = 0;
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,247 +0,0 @@
|
||||
/*
|
||||
* \brief Linux emulation code
|
||||
* \author Josef Soentgen
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2014-03-07
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2020 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/skbuff.h>
|
||||
#include <linux/usb.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/cdc.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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL(cdc_parse_cdc_header);
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* \brief Lx C env
|
||||
* \author Josef Soentgen
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2016-03-04
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2020 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,252 +0,0 @@
|
||||
/*
|
||||
* \brief USB modem driver
|
||||
* \author Stefan Kalkowski
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2018-06-07
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 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>
|
||||
|
||||
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;
|
||||
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::set_config(Usb::Device_descriptor const &desc)
|
||||
{
|
||||
/* Huawei ME906s */
|
||||
if (desc.vendor_id == 0x12d1 && desc.product_id == 0x15c1) {
|
||||
Genode::log("Found Huawei ME906s choosing configuration #3");
|
||||
/* set unconfigured first */
|
||||
Sync_packet(usb).config(0);
|
||||
/* configuration 3 is MBIM for this modem */
|
||||
Sync_packet(usb).config(3);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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->bus->sysdev = (device*) (&driver.terminal_root);
|
||||
|
||||
udev->descriptor.idVendor = dev_desc.vendor_id;
|
||||
udev->descriptor.idProduct = dev_desc.product_id;
|
||||
udev->descriptor.bcdDevice = dev_desc.device_release;
|
||||
|
||||
|
||||
set_config(dev_desc);
|
||||
/* re-read config */
|
||||
usb.config_descriptor(&dev_desc, &config_desc);
|
||||
|
||||
/* device specific configuration profile */
|
||||
|
||||
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;
|
||||
|
||||
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();
|
||||
driver.env.parent().announce(driver.ep.manage(driver.terminal_root));
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
LX_MUTEX_INIT(wdm_mutex);
|
||||
|
||||
Driver * driver = reinterpret_cast<Driver*>(arg);
|
||||
|
||||
tasklet_wq = alloc_workqueue("tasklet_wq", 0, 0);
|
||||
|
||||
skb_init();
|
||||
module_usbnet_init();
|
||||
module_wdm_driver_init();
|
||||
module_cdc_ncm_driver_init();
|
||||
module_cdc_mbim_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,29 +0,0 @@
|
||||
TARGET := usb_modem_drv
|
||||
SRC_C := dummies.c lxc.c
|
||||
SRC_CC := main.cc lx_emul.cc terminal.cc fec_nic.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_modem_include lx_kit_setjmp nic_driver format
|
||||
|
||||
USB_CONTRIB_DIR := $(call select_from_ports,dde_linux)/src/drivers/usb_modem
|
||||
|
||||
INC_DIR += $(PRG_DIR)
|
||||
INC_DIR += $(REP_DIR)/src/include
|
||||
|
||||
SRC_C += drivers/net/usb/usbnet.c
|
||||
SRC_C += drivers/net/usb/cdc_ncm.c
|
||||
SRC_C += drivers/net/usb/cdc_mbim.c
|
||||
SRC_C += drivers/usb/class/cdc-wdm.c
|
||||
SRC_C += net/core/skbuff.c
|
||||
SRC_C += net/ethernet/eth.c
|
||||
|
||||
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 %.c $(USB_CONTRIB_DIR)
|
||||
vpath %.cc $(REP_DIR)/src/lib/legacy/lx_kit
|
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* \brief USB modem driver terminal service
|
||||
* \author Sebastian Sumpf
|
||||
* \author Josef Soentgen
|
||||
* \date 2020-12-02
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020 Genode Labs GmbH
|
||||
*
|
||||
* This file is distributed under the terms of the GNU General Public License
|
||||
* version 2.
|
||||
*/
|
||||
|
||||
#include <terminal.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>
|
||||
|
||||
using namespace Terminal;
|
||||
|
||||
|
||||
Session_component::Session_component(Genode::Env &env,
|
||||
Genode::size_t io_buffer_size,
|
||||
usb_class_driver *class_driver)
|
||||
:
|
||||
_io_buffer(env.ram(), env.rm(), io_buffer_size),
|
||||
_io_buffer_size(io_buffer_size),
|
||||
_class_driver(class_driver)
|
||||
{
|
||||
if (class_driver == nullptr) {
|
||||
Genode::error("No class driver for terminal");
|
||||
throw Genode::Service_denied();
|
||||
}
|
||||
|
||||
Lx::scheduler().schedule();
|
||||
}
|
||||
|
||||
void Session_component::_run_wdm_device(void *args)
|
||||
{
|
||||
Session_component *session = static_cast<Session_component *>(args);
|
||||
|
||||
usb_class_driver *driver = session->_class_driver;
|
||||
|
||||
int err = -1;
|
||||
struct file file { };
|
||||
|
||||
if ((err = driver->fops->open(nullptr, &file))) {
|
||||
Genode::error("Could not open WDM device: ", err);
|
||||
return;
|
||||
}
|
||||
|
||||
session->_wdm_device = file.private_data;
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
//XXX: close
|
||||
}
|
||||
|
||||
|
||||
void Session_component::_run_wdm_write(void *args)
|
||||
{
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
|
||||
Session_component *session = static_cast<Session_component *>(args);
|
||||
usb_class_driver *driver = session->_class_driver;
|
||||
|
||||
struct file file { .private_data = session->_wdm_device };
|
||||
|
||||
while (1) {
|
||||
ssize_t length = driver->fops->write(&file, session->buffer(),
|
||||
session->_data_avail, nullptr);
|
||||
if (length < 0) {
|
||||
Genode::error("WDM write error: ", length);
|
||||
}
|
||||
|
||||
session->_schedule_read();
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Session_component::_run_wdm_read(void *args)
|
||||
{
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
Session_component *session = static_cast<Session_component *>(args);
|
||||
|
||||
usb_class_driver *driver = session->_class_driver;
|
||||
|
||||
struct file file { .private_data = session->_wdm_device };
|
||||
|
||||
while (1) {
|
||||
ssize_t length = driver->fops->read(&file, session->buffer(), 0x1000, nullptr);
|
||||
if (length > 0) {
|
||||
session->_data_avail = length;
|
||||
session->signal_data_avail();
|
||||
}
|
||||
Lx::scheduler().current()->block_and_schedule();
|
||||
}
|
||||
}
|
@ -1,180 +0,0 @@
|
||||
/*
|
||||
* \brief Service providing the 'Terminal_session' interface for a Linux file
|
||||
* \author Josef Soentgen
|
||||
* \author Sebastian Sumpf
|
||||
* \date 2020-07-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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__USB_MODEM__TERMINAL_H_
|
||||
#define _SRC__DRIVERS__USB_MODEM__TERMINAL_H_
|
||||
|
||||
/* Genode includes */
|
||||
#include <base/attached_ram_dataspace.h>
|
||||
#include <base/log.h>
|
||||
#include <os/session_policy.h>
|
||||
#include <root/component.h>
|
||||
#include <terminal_session/terminal_session.h>
|
||||
|
||||
#include <legacy/lx_kit/scheduler.h>
|
||||
|
||||
namespace Terminal {
|
||||
class Session_component;
|
||||
class Root;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
struct usb_class_driver;
|
||||
}
|
||||
|
||||
class Terminal::Session_component : public Genode::Rpc_object<Session, Session_component>
|
||||
{
|
||||
using size_t = Genode::size_t;
|
||||
|
||||
private:
|
||||
|
||||
enum State { WRITE, READ };
|
||||
|
||||
Genode::Attached_ram_dataspace _io_buffer;
|
||||
Genode::Signal_context_capability _read_avail_sigh { };
|
||||
|
||||
State _state { WRITE };
|
||||
size_t _data_avail { 0 };
|
||||
size_t _io_buffer_size;
|
||||
void *_wdm_device { nullptr };
|
||||
usb_class_driver *_class_driver { nullptr };
|
||||
|
||||
static void _run_wdm_device(void *args);
|
||||
static void _run_wdm_write(void *args);
|
||||
static void _run_wdm_read(void *args);
|
||||
|
||||
Lx::Task _task_write { _run_wdm_write, this, "wdm_task_write",
|
||||
Lx::Task::PRIORITY_1, Lx::scheduler() };
|
||||
|
||||
Lx::Task _task_read { _run_wdm_read, this, "wdm_task_read",
|
||||
Lx::Task::PRIORITY_1, Lx::scheduler() };
|
||||
|
||||
Lx::Task _task_device { _run_wdm_device, this, "wdm_task_devie",
|
||||
Lx::Task::PRIORITY_1, Lx::scheduler() };
|
||||
void _schedule_read()
|
||||
{
|
||||
_task_read.unblock();
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Session_component(Genode::Env &env,
|
||||
Genode::size_t io_buffer_size,
|
||||
usb_class_driver *class_driver);
|
||||
|
||||
/********************************
|
||||
** Terminal session interface **
|
||||
********************************/
|
||||
|
||||
Size size() override { return Size(0, 0); }
|
||||
|
||||
bool avail() override
|
||||
{
|
||||
return _data_avail > 0;
|
||||
}
|
||||
|
||||
Genode::size_t _read(Genode::size_t dst_len)
|
||||
{
|
||||
if (_state != READ) return 0;
|
||||
|
||||
size_t length = Genode::min(dst_len, _data_avail);
|
||||
if (dst_len < _data_avail)
|
||||
Genode::warning("dst_len < data_avail (", dst_len, " < ", _data_avail, ") not supported");
|
||||
|
||||
_data_avail -= length;
|
||||
|
||||
if (_data_avail == 0) {
|
||||
_state = WRITE;
|
||||
_schedule_read();
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
Genode::size_t _write(Genode::size_t num_bytes)
|
||||
{
|
||||
if (_state == READ) return 0;
|
||||
|
||||
_data_avail = num_bytes;
|
||||
_state = WRITE;
|
||||
|
||||
_task_write.unblock();
|
||||
Lx::scheduler().schedule();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Genode::Dataspace_capability _dataspace()
|
||||
{
|
||||
return _io_buffer.cap();
|
||||
}
|
||||
|
||||
void read_avail_sigh(Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
_read_avail_sigh = sigh;
|
||||
}
|
||||
|
||||
void connected_sigh(Genode::Signal_context_capability sigh) override
|
||||
{
|
||||
Genode::Signal_transmitter(sigh).submit();
|
||||
}
|
||||
|
||||
void size_changed_sigh(Genode::Signal_context_capability) override { }
|
||||
|
||||
size_t read(void *, size_t) override { return 0; }
|
||||
size_t write(void const *, size_t) override { return 0; }
|
||||
|
||||
char *buffer() { return _io_buffer.local_addr<char>(); }
|
||||
|
||||
void signal_data_avail()
|
||||
{
|
||||
if (_read_avail_sigh.valid() == false) return;
|
||||
_state = READ;
|
||||
Genode::Signal_transmitter(_read_avail_sigh).submit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Terminal::Root : public Genode::Root_component<Session_component>
|
||||
{
|
||||
private:
|
||||
|
||||
Genode::Env &_env;
|
||||
usb_class_driver *_class_driver { nullptr };
|
||||
|
||||
protected:
|
||||
|
||||
Session_component *_create_session(const char *args) override
|
||||
{
|
||||
Genode::size_t const io_buffer_size = 4096ul;
|
||||
return new (md_alloc())
|
||||
Session_component(_env, io_buffer_size, _class_driver);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
Root(Genode::Env &env,
|
||||
Genode::Allocator &md_alloc)
|
||||
:
|
||||
Genode::Root_component<Session_component>(&env.ep().rpc_ep(), &md_alloc),
|
||||
_env(env)
|
||||
{ }
|
||||
|
||||
void class_driver(usb_class_driver *class_driver) { _class_driver = class_driver; }
|
||||
};
|
||||
|
||||
#endif /* _SRC__DRIVERS__USB_MODEM__TERMINAL_H_ */
|
@ -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)
|
||||
:
|
||||
Fec_nic { 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 <fec_nic.h>
|
||||
|
||||
namespace Genode {
|
||||
|
||||
class Uplink_client;
|
||||
}
|
||||
|
||||
|
||||
class Genode::Uplink_client : public Fec_nic,
|
||||
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);
|
||||
|
||||
|
||||
/*************
|
||||
** Fec_nic **
|
||||
*************/
|
||||
|
||||
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