mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-21 06:33:31 +00:00
usb_net: Add cdc_ether ECM support
* Enable ECM devices * Allow disconnect of devices * Handle link state correctly * Required by PinePhone's USB modem issue #4557
This commit is contained in:
parent
96b147b63d
commit
64c81e2846
@ -8,7 +8,7 @@ LX_EMUL_H := $(REP_DIR)/src/drivers/usb_net/lx_emul.h
|
|||||||
# of these header files we create a symlink to 'lx_emul.h'.
|
# 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) \
|
SCAN_DIRS := $(addprefix $(USB_NET_CONTRIB_DIR)/include/, asm-generic linux uapi net) \
|
||||||
$(addprefix $(USB_NET_CONTRIB_DIR)/, drivers net)
|
$(addprefix $(USB_NET_CONTRIB_DIR)/, drivers net lib)
|
||||||
GEN_INCLUDES := $(shell grep -rIh "^\#include .*\/" $(SCAN_DIRS) |\
|
GEN_INCLUDES := $(shell grep -rIh "^\#include .*\/" $(SCAN_DIRS) |\
|
||||||
sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" |\
|
sed "s/^\#include [^<\"]*[<\"]\([^>\"]*\)[>\"].*/\1/" |\
|
||||||
sort | uniq)
|
sort | uniq)
|
||||||
|
@ -1 +1 @@
|
|||||||
447158aa8aa24d4e2925a0479d8710a2d7d738e9
|
f56657b5edae9fb069db1b5846bca4aebe7ce542
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
|
|
||||||
/* Linux emulation environment includes */
|
/* Linux emulation environment includes */
|
||||||
#include <legacy/lx_kit/scheduler.h>
|
#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_device_id;
|
||||||
struct usb_interface;
|
struct usb_interface;
|
||||||
@ -93,6 +97,55 @@ struct Driver
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Sync_packet : public Usb::Completion
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Usb::Session_client & _usb;
|
||||||
|
Usb::Packet_descriptor _packet { _usb.source()->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;
|
Devices devices;
|
||||||
Genode::Env &env;
|
Genode::Env &env;
|
||||||
Genode::Entrypoint &ep { env.ep() };
|
Genode::Entrypoint &ep { env.ep() };
|
||||||
|
@ -27,14 +27,6 @@ u16 bitrev16(u16 in)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct usb_cdc_parsed_header;
|
|
||||||
struct usb_interface;
|
|
||||||
int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, struct usb_interface *intf, u8 *buffer, int buflen)
|
|
||||||
{
|
|
||||||
TRACE_AND_STOP;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u16 crc16(u16 crc, const u8 *buffer, size_t len)
|
u16 crc16(u16 crc, const u8 *buffer, size_t len)
|
||||||
{
|
{
|
||||||
TRACE_AND_STOP;
|
TRACE_AND_STOP;
|
||||||
@ -53,24 +45,12 @@ __wsum csum_partial(const void *buff, int len, __wsum sum)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void * dev_get_drvdata(const struct device *dev)
|
|
||||||
{
|
|
||||||
TRACE_AND_STOP;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int device_set_wakeup_enable(struct device *dev, bool enable)
|
int device_set_wakeup_enable(struct device *dev, bool enable)
|
||||||
{
|
{
|
||||||
TRACE_AND_STOP;
|
TRACE_AND_STOP;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sk_buff;
|
|
||||||
void dev_kfree_skb_any(struct sk_buff *skb)
|
|
||||||
{
|
|
||||||
TRACE_AND_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dst_release(struct dst_entry *dst)
|
void dst_release(struct dst_entry *dst)
|
||||||
{
|
{
|
||||||
TRACE_AND_STOP;
|
TRACE_AND_STOP;
|
||||||
@ -95,11 +75,6 @@ bool file_ns_capable(const struct file *file, struct user_namespace *ns, int cap
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_netdev(struct net_device * ndev)
|
|
||||||
{
|
|
||||||
TRACE_AND_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
void free_uid(struct user_struct * user)
|
void free_uid(struct user_struct * user)
|
||||||
{
|
{
|
||||||
TRACE_AND_STOP;
|
TRACE_AND_STOP;
|
||||||
@ -129,12 +104,6 @@ bool gfp_pfmemalloc_allowed(gfp_t gfp_flags)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hex2bin(u8 *dst, const char *src, size_t count)
|
|
||||||
{
|
|
||||||
TRACE_AND_STOP;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int in_irq()
|
int in_irq()
|
||||||
{
|
{
|
||||||
TRACE_AND_STOP;
|
TRACE_AND_STOP;
|
||||||
@ -255,11 +224,6 @@ void read_unlock_bh(rwlock_t * l)
|
|||||||
TRACE_AND_STOP;
|
TRACE_AND_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void unregister_netdev(struct net_device * dev)
|
|
||||||
{
|
|
||||||
TRACE_AND_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
void secpath_reset(struct sk_buff * skb)
|
void secpath_reset(struct sk_buff * skb)
|
||||||
{
|
{
|
||||||
TRACE;
|
TRACE;
|
||||||
@ -267,7 +231,7 @@ void secpath_reset(struct sk_buff * skb)
|
|||||||
|
|
||||||
void __set_current_state(int state)
|
void __set_current_state(int state)
|
||||||
{
|
{
|
||||||
TRACE_AND_STOP;
|
TRACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sg_init_table(struct scatterlist *sg, unsigned int arg)
|
void sg_init_table(struct scatterlist *sg, unsigned int arg)
|
||||||
@ -318,7 +282,7 @@ size_t strlcpy(char *dest, const char *src, size_t size)
|
|||||||
|
|
||||||
void tasklet_kill(struct tasklet_struct *t)
|
void tasklet_kill(struct tasklet_struct *t)
|
||||||
{
|
{
|
||||||
TRACE_AND_STOP;
|
TRACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void trace_consume_skb(struct sk_buff *skb)
|
void trace_consume_skb(struct sk_buff *skb)
|
||||||
@ -351,17 +315,21 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct usb_driver;
|
struct usb_driver;
|
||||||
int usb_driver_claim_interface(struct usb_driver *driver, struct usb_interface *iface, void *priv)
|
struct usb_interface;
|
||||||
{
|
|
||||||
TRACE_AND_STOP;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface)
|
void usb_driver_release_interface(struct usb_driver *driver, struct usb_interface *iface)
|
||||||
{
|
{
|
||||||
TRACE_AND_STOP;
|
TRACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* only called to kill interrupt urb in usbnet.c */
|
||||||
|
struct urb;
|
||||||
|
void usb_kill_urb(struct urb *urb)
|
||||||
|
{
|
||||||
|
TRACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct usb_anchor;
|
struct usb_anchor;
|
||||||
struct urb *usb_get_from_anchor(struct usb_anchor *anchor)
|
struct urb *usb_get_from_anchor(struct usb_anchor *anchor)
|
||||||
{
|
{
|
||||||
@ -369,12 +337,6 @@ struct urb *usb_get_from_anchor(struct usb_anchor *anchor)
|
|||||||
return NULL;
|
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)
|
int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, void *data, int len, int *actual_length, int timeout)
|
||||||
{
|
{
|
||||||
TRACE_AND_STOP;
|
TRACE_AND_STOP;
|
||||||
@ -383,13 +345,7 @@ int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, void *data,
|
|||||||
|
|
||||||
void usb_scuttle_anchored_urbs(struct usb_anchor *anchor)
|
void usb_scuttle_anchored_urbs(struct usb_anchor *anchor)
|
||||||
{
|
{
|
||||||
TRACE_AND_STOP;
|
TRACE;
|
||||||
}
|
|
||||||
|
|
||||||
int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
|
|
||||||
{
|
|
||||||
TRACE_AND_STOP;
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ktime_t ktime_get_real(void)
|
ktime_t ktime_get_real(void)
|
||||||
@ -419,29 +375,20 @@ void put_page(struct page *page)
|
|||||||
TRACE_AND_STOP;
|
TRACE_AND_STOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct usb_interface *usb_ifnum_to_if(const struct usb_device *dev, unsigned ifnum)
|
int usb_unlink_urb(struct urb *urb)
|
||||||
{
|
|
||||||
TRACE_AND_STOP;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void usb_kill_urb(struct urb *urb)
|
|
||||||
{
|
|
||||||
TRACE_AND_STOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
int usb_set_interface(struct usb_device *dev, int ifnum, int alternate)
|
|
||||||
{
|
{
|
||||||
TRACE;
|
TRACE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_unlink_urb(struct urb *urb)
|
|
||||||
|
struct urb *usb_get_urb(struct urb *urb)
|
||||||
{
|
{
|
||||||
TRACE_AND_STOP;
|
TRACE;
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void usleep_range(unsigned long min, unsigned long max)
|
void usleep_range(unsigned long min, unsigned long max)
|
||||||
{
|
{
|
||||||
TRACE;
|
TRACE;
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
#include <legacy/lx_emul/extern_c_begin.h>
|
#include <legacy/lx_emul/extern_c_begin.h>
|
||||||
|
|
||||||
#include <linux/mii.h>
|
#include <linux/mii.h>
|
||||||
|
#include <linux/usb/usbnet.h>
|
||||||
|
|
||||||
|
|
||||||
static int usb_match_device(struct usb_device *dev,
|
static int usb_match_device(struct usb_device *dev,
|
||||||
const struct usb_device_id *id)
|
const struct usb_device_id *id)
|
||||||
@ -203,12 +205,6 @@ Genode::Ram_dataspace_capability Lx::backend_alloc(Genode::addr_t size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Genode::addr_t Lx::backend_dma_addr(Genode::Ram_dataspace_capability)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int usb_register_driver(struct usb_driver * driver, struct module *, const char *)
|
int usb_register_driver(struct usb_driver * driver, struct module *, const char *)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&driver->dynids.list);
|
INIT_LIST_HEAD(&driver->dynids.list);
|
||||||
@ -217,25 +213,66 @@ int usb_register_driver(struct usb_driver * driver, struct module *, const char
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
void Driver::Device::probe_interface(usb_interface * iface, usb_device_id * id)
|
||||||
{
|
{
|
||||||
using Le = Genode::List_element<Lx_driver>;
|
using Le = Genode::List_element<Lx_driver>;
|
||||||
for (Le *le = Lx_driver::list().first(); le; le = le->next()) {
|
for (Le *le = Lx_driver::list().first(); le; le = le->next()) {
|
||||||
usb_device_id * id = le->object()->match(iface);
|
usb_device_id * id = le->object()->match(iface);
|
||||||
if (id && le->object()->probe(iface, id)) return;
|
|
||||||
|
if (id) {
|
||||||
|
int ret = le->object()->probe(iface, id);
|
||||||
|
if (ret == 0) return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Driver::Device::remove_interface(usb_interface * iface)
|
void Driver::Device::remove_interface(usb_interface * iface)
|
||||||
{
|
{
|
||||||
to_usb_driver(iface->dev.driver)->disconnect(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++) {
|
for (unsigned i = 0; i < iface->num_altsetting; i++) {
|
||||||
if (iface->altsetting[i].extra)
|
if (iface->altsetting[i].extra)
|
||||||
kfree(iface->altsetting[i].extra);
|
kfree(iface->altsetting[i].extra);
|
||||||
kfree(iface->altsetting[i].endpoint);
|
kfree(iface->altsetting[i].endpoint);
|
||||||
kfree(iface->altsetting);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kfree(iface->altsetting);
|
||||||
kfree(iface);
|
kfree(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,6 +387,16 @@ struct net_device *alloc_etherdev(int sizeof_priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
void *__alloc_percpu(size_t size, size_t align)
|
||||||
{
|
{
|
||||||
return kmalloc(size, 0);
|
return kmalloc(size, 0);
|
||||||
@ -379,16 +426,25 @@ int register_netdev(struct net_device *dev)
|
|||||||
dev->state |= 1 << __LINK_STATE_START;
|
dev->state |= 1 << __LINK_STATE_START;
|
||||||
|
|
||||||
int err = dev->netdev_ops->ndo_open(dev);
|
int err = dev->netdev_ops->ndo_open(dev);
|
||||||
|
|
||||||
if (err) return err;
|
if (err) return err;
|
||||||
|
|
||||||
if (dev->netdev_ops->ndo_set_rx_mode)
|
if (dev->netdev_ops->ndo_set_rx_mode)
|
||||||
dev->netdev_ops->ndo_set_rx_mode(dev);
|
dev->netdev_ops->ndo_set_rx_mode(dev);
|
||||||
|
|
||||||
single_net_device = dev;
|
single_net_device = dev;
|
||||||
return 0;
|
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 *
|
net_device *
|
||||||
Linux_network_session_base::
|
Linux_network_session_base::
|
||||||
_register_session(Linux_network_session_base &session,
|
_register_session(Linux_network_session_base &session,
|
||||||
@ -431,6 +487,12 @@ int dev_set_drvdata(struct device *dev, void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void * dev_get_drvdata(const struct device *dev)
|
||||||
|
{
|
||||||
|
return dev->driver_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int netif_running(const struct net_device *dev)
|
int netif_running(const struct net_device *dev)
|
||||||
{
|
{
|
||||||
return dev->state & (1 << __LINK_STATE_START);
|
return dev->state & (1 << __LINK_STATE_START);
|
||||||
@ -485,6 +547,11 @@ int netif_rx(struct sk_buff * skb)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dev_kfree_skb_any(struct sk_buff *skb)
|
||||||
|
{
|
||||||
|
dev_kfree_skb(skb);
|
||||||
|
}
|
||||||
|
|
||||||
int is_valid_ether_addr(const u8 * a)
|
int is_valid_ether_addr(const u8 * a)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < ETH_ALEN; i++)
|
for (unsigned i = 0; i < ETH_ALEN; i++)
|
||||||
@ -551,3 +618,5 @@ void page_frag_free(void *addr)
|
|||||||
Lx::Malloc::dma().free_large(page->addr);
|
Lx::Malloc::dma().free_large(page->addr);
|
||||||
kfree(page);
|
kfree(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,6 +120,8 @@ int dev_set_drvdata(struct device *dev, void *data);
|
|||||||
#define pr_notice(fmt, ...) printk(KERN_NOTICE fmt, ##__VA_ARGS__)
|
#define pr_notice(fmt, ...) printk(KERN_NOTICE fmt, ##__VA_ARGS__)
|
||||||
#define pr_emerg(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__)
|
#define pr_emerg(fmt, ...) printk(KERN_INFO fmt, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define try_then_request_module(x, mod...) (x)
|
||||||
|
|
||||||
struct bus_type
|
struct bus_type
|
||||||
{
|
{
|
||||||
int (*match)(struct device *dev, struct device_driver *drv);
|
int (*match)(struct device *dev, struct device_driver *drv);
|
||||||
@ -190,6 +192,7 @@ const char *dev_name(const struct device *dev);
|
|||||||
struct __una_u16 { u16 x; } __attribute__((packed));
|
struct __una_u16 { u16 x; } __attribute__((packed));
|
||||||
struct __una_u32 { u32 x; } __attribute__((packed));
|
struct __una_u32 { u32 x; } __attribute__((packed));
|
||||||
|
|
||||||
|
#define get_unaligned(ptr) (*ptr)
|
||||||
u16 get_unaligned_le16(const void *p);
|
u16 get_unaligned_le16(const void *p);
|
||||||
u32 get_unaligned_le32(const void *p);
|
u32 get_unaligned_le32(const void *p);
|
||||||
|
|
||||||
@ -534,6 +537,12 @@ const void *of_get_mac_address(struct device_node *np);
|
|||||||
u16 bitrev16(u16 in);
|
u16 bitrev16(u16 in);
|
||||||
u16 crc16(u16 crc, const u8 *buffer, size_t len);
|
u16 crc16(u16 crc, const u8 *buffer, size_t len);
|
||||||
int hex2bin(u8 *dst, const char *src, size_t count);
|
int hex2bin(u8 *dst, const char *src, size_t count);
|
||||||
|
char *hex_byte_pack(char *buf, u8 byte);
|
||||||
|
|
||||||
|
#define hex_asc_upper_lo(x) hex_asc_upper[((x) & 0x0f)]
|
||||||
|
#define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
|
||||||
|
#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4]
|
||||||
|
|
||||||
|
|
||||||
#define this_cpu_ptr(ptr) ptr
|
#define this_cpu_ptr(ptr) ptr
|
||||||
|
|
||||||
@ -918,6 +927,7 @@ void *kmap_atomic(struct page *page);
|
|||||||
void kunmap_atomic(void *addr);
|
void kunmap_atomic(void *addr);
|
||||||
|
|
||||||
#define CONFIG_LOCKDEP 1
|
#define CONFIG_LOCKDEP 1
|
||||||
|
#define CONFIG_NLS_DEFAULT "iso8859-1"
|
||||||
|
|
||||||
struct partial_page
|
struct partial_page
|
||||||
{
|
{
|
||||||
|
@ -13,7 +13,13 @@
|
|||||||
|
|
||||||
/* linux includes */
|
/* linux includes */
|
||||||
#include <lx_emul.h>
|
#include <lx_emul.h>
|
||||||
|
#include <linux/ctype.h>
|
||||||
|
#include <linux/nls.h>
|
||||||
#include <linux/skbuff.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 */
|
/* local includes */
|
||||||
#include <lxc.h>
|
#include <lxc.h>
|
||||||
@ -63,3 +69,356 @@ unsigned char *lxc_skb_put(struct sk_buff *skb, size_t len)
|
|||||||
{
|
{
|
||||||
return skb_put(skb, 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);
|
||||||
|
|
||||||
|
@ -39,15 +39,22 @@ void Driver::Device::scan_altsettings(usb_interface * iface,
|
|||||||
if (iface_desc.active)
|
if (iface_desc.active)
|
||||||
iface->cur_altsetting = &iface->altsetting[alt_idx];
|
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*)
|
iface->altsetting[alt_idx].endpoint = (usb_host_endpoint*)
|
||||||
kzalloc(sizeof(usb_host_endpoint)*iface->altsetting[alt_idx].desc.bNumEndpoints, GFP_KERNEL);
|
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++) {
|
for (unsigned i = 0; i < iface->altsetting[alt_idx].desc.bNumEndpoints; i++) {
|
||||||
Usb::Endpoint_descriptor ep_desc;
|
Usb::Endpoint_descriptor ep_desc[7];
|
||||||
usb.endpoint_descriptor(iface_idx, alt_idx, i, &ep_desc);
|
usb.endpoint_descriptor(iface_idx, alt_idx, i, ep_desc);
|
||||||
Genode::memcpy(&iface->altsetting[alt_idx].endpoint[i].desc,
|
Genode::memcpy(&iface->altsetting[alt_idx].endpoint[i].desc,
|
||||||
&ep_desc, sizeof(usb_endpoint_descriptor));
|
ep_desc, sizeof(usb_endpoint_descriptor));
|
||||||
int epnum = usb_endpoint_num(&iface->altsetting[alt_idx].endpoint[i].desc);
|
int epnum = usb_endpoint_num(&iface->altsetting[alt_idx].endpoint[i].desc);
|
||||||
if (usb_endpoint_dir_out(&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];
|
udev->ep_out[epnum] = &iface->altsetting[alt_idx].endpoint[i];
|
||||||
@ -70,11 +77,7 @@ void Driver::Device::scan_interfaces(unsigned iface_idx)
|
|||||||
for (unsigned i = 0; i < iface->num_altsetting; i++)
|
for (unsigned i = 0; i < iface->num_altsetting; i++)
|
||||||
scan_altsettings(iface, iface_idx, i);
|
scan_altsettings(iface, iface_idx, i);
|
||||||
|
|
||||||
struct usb_device_id id;
|
|
||||||
probe_interface(iface, &id);
|
|
||||||
udev->config->interface[iface_idx] = iface;
|
udev->config->interface[iface_idx] = iface;
|
||||||
|
|
||||||
driver.activate_network_session();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -101,6 +104,17 @@ void Driver::Device::register_device()
|
|||||||
|
|
||||||
for (unsigned i = 0; i < config_desc.num_interfaces; i++)
|
for (unsigned i = 0; i < config_desc.num_interfaces; i++)
|
||||||
scan_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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -20,9 +20,14 @@ SRC_C += drivers/net/usb/cdc_ether.c
|
|||||||
SRC_C += drivers/net/usb/rndis_host.c
|
SRC_C += drivers/net/usb/rndis_host.c
|
||||||
SRC_C += drivers/net/usb/smsc95xx.c
|
SRC_C += drivers/net/usb/smsc95xx.c
|
||||||
SRC_C += drivers/net/usb/usbnet.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/core/skbuff.c
|
||||||
SRC_C += net/ethernet/eth.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 \
|
CC_C_OPT += -Wno-comment -Wno-int-conversion -Wno-incompatible-pointer-types \
|
||||||
-Wno-unused-variable -Wno-pointer-sign -Wno-uninitialized \
|
-Wno-unused-variable -Wno-pointer-sign -Wno-uninitialized \
|
||||||
-Wno-maybe-uninitialized -Wno-format -Wno-discarded-qualifiers \
|
-Wno-maybe-uninitialized -Wno-format -Wno-discarded-qualifiers \
|
||||||
|
@ -8,6 +8,9 @@ linux-x.x.x/drivers/net/usb/rndis_host.c
|
|||||||
linux-x.x.x/drivers/net/usb/smsc95xx.h
|
linux-x.x.x/drivers/net/usb/smsc95xx.h
|
||||||
linux-x.x.x/drivers/net/usb/smsc95xx.c
|
linux-x.x.x/drivers/net/usb/smsc95xx.c
|
||||||
linux-x.x.x/drivers/net/usb/usbnet.c
|
linux-x.x.x/drivers/net/usb/usbnet.c
|
||||||
|
linux-x.x.x/fs/nls/nls_base.c
|
||||||
|
linux-x.x.x/lib/ctype.c
|
||||||
|
linux-x.x.x/lib/hexdump.c
|
||||||
linux-x.x.x/net/core/skbuff.c
|
linux-x.x.x/net/core/skbuff.c
|
||||||
linux-x.x.x/net/ethernet/eth.c
|
linux-x.x.x/net/ethernet/eth.c
|
||||||
linux-x.x.x/include/asm-generic/atomic64.h
|
linux-x.x.x/include/asm-generic/atomic64.h
|
||||||
@ -18,6 +21,7 @@ linux-x.x.x/include/asm-generic/bitops/fls.h
|
|||||||
linux-x.x.x/include/asm-generic/bitops/fls64.h
|
linux-x.x.x/include/asm-generic/bitops/fls64.h
|
||||||
linux-x.x.x/include/asm-generic/bitops/non-atomic.h
|
linux-x.x.x/include/asm-generic/bitops/non-atomic.h
|
||||||
linux-x.x.x/include/linux/cgroup-defs.h
|
linux-x.x.x/include/linux/cgroup-defs.h
|
||||||
|
linux-x.x.x/include/linux/ctype.h
|
||||||
linux-x.x.x/include/linux/errqueue.h
|
linux-x.x.x/include/linux/errqueue.h
|
||||||
linux-x.x.x/include/linux/ethtool.h
|
linux-x.x.x/include/linux/ethtool.h
|
||||||
linux-x.x.x/include/linux/if_ether.h
|
linux-x.x.x/include/linux/if_ether.h
|
||||||
@ -30,6 +34,7 @@ linux-x.x.x/include/linux/mdio.h
|
|||||||
linux-x.x.x/include/linux/mod_devicetable.h
|
linux-x.x.x/include/linux/mod_devicetable.h
|
||||||
linux-x.x.x/include/linux/netdev_features.h
|
linux-x.x.x/include/linux/netdev_features.h
|
||||||
linux-x.x.x/include/linux/net.h
|
linux-x.x.x/include/linux/net.h
|
||||||
|
linux-x.x.x/include/linux/nls.h
|
||||||
linux-x.x.x/include/linux/phy.h
|
linux-x.x.x/include/linux/phy.h
|
||||||
linux-x.x.x/include/linux/rbtree.h
|
linux-x.x.x/include/linux/rbtree.h
|
||||||
linux-x.x.x/include/linux/rculist.h
|
linux-x.x.x/include/linux/rculist.h
|
||||||
@ -42,6 +47,7 @@ linux-x.x.x/include/linux/swab.h
|
|||||||
linux-x.x.x/include/linux/usb.h
|
linux-x.x.x/include/linux/usb.h
|
||||||
linux-x.x.x/include/linux/usb/ch9.h
|
linux-x.x.x/include/linux/usb/ch9.h
|
||||||
linux-x.x.x/include/linux/usb/cdc.h
|
linux-x.x.x/include/linux/usb/cdc.h
|
||||||
|
linux-x.x.x/include/linux/usb/quirks.h
|
||||||
linux-x.x.x/include/linux/usb/rndis_host.h
|
linux-x.x.x/include/linux/usb/rndis_host.h
|
||||||
linux-x.x.x/include/linux/usb/usbnet.h
|
linux-x.x.x/include/linux/usb/usbnet.h
|
||||||
linux-x.x.x/include/net/dst.h
|
linux-x.x.x/include/net/dst.h
|
||||||
|
Loading…
Reference in New Issue
Block a user