<commit_before>/**
 * @file
 * @brief
 *    For more details about configurations and interfaces see
 *    usb specification 1.1 chapter 9.
 *
 * @author  <NAME>
 * @date    05.04.2014
 */

#include <mem/misc/pool.h>
#include <mem/sysmalloc.h>
#include <kernel/printk.h>
#include <kernel/panic.h>
#include <embox/unit.h>
#include <drivers/usb/usb_cdc.h>
#include <drivers/usb/usb_driver.h>
#include <kernel/printk.h>
#include <stdlib.h>
#include <string.h>

EMBOX_UNIT_INIT(usb_cdc_init);

POOL_DEF(cdc_classes, struct usb_class_cdc, USB_CDC_MAX_DEVS);

/* Storage for device configuration*/
static char cdc_conf[16];

#define INTERFACE_DESC_OFFSET          (sizeof (struct usb_desc_configuration))
#define CS_INTERFACE                   0x24

/* Configuration */
static void cdc_get_conf_len_hnd(struct usb_request *req, void *arg);
static void cdc_get_conf(struct usb_dev *dev, struct usb_class_cdc *cdc,
		size_t idx, size_t len, usb_request_notify_hnd_t cb);
static void cdc_get_conf_content_hnd(struct usb_request *req, void *arg);
static void cdc_get_conf_hnd(struct usb_request *req, void *arg);
static void cdc_next_conf(struct usb_dev *dev);

/* Endpoint */
static size_t cdc_skip_func_descs(char *start);
static size_t cdc_skip_endpoints(char *start);
static void cdc_get_endpoints(struct usb_dev *dev, struct usb_class_cdc *cdc);

/* Misc */
static int is_rndis(struct usb_desc_interface *desc);

/**
 * Skip all functional descriptors.
 * Return size of all functional descriptors.
 * @see ecm120.pdf (Subclass Specification for
 *  Ethernet Control Model Devices) Section 5
 * XXX skip is a default action now, but it is possible to redefine this behavior
 */
static size_t cdc_skip_func_descs(char *start) {
	char *cur = start;

	while (1) {
		uint8_t len, type;

		type = *(cur + 1);
		if (type == CS_INTERFACE) {
			len = *cur;
			cur += len;
		} else {
			break;
		}
	}

	return (cur - start);
}

/*
 * @see ecm120.pdf (Subclass Specification for
 *  Ethernet Control Model Devices) Section 5
 */
static size_t cdc_skip_endpoints(char *start) {
	char *cur = start;

	while (1) {
		uint8_t len, type;

		type = *(cur + 1);
		if (type == USB_DESC_TYPE_ENDPOINT) {
			len = *cur;
			cur += len;
		} else {
			break;
		}
	}

	return (cur - start);
}

struct usb_desc_interface *cdc_get_interface(
		struct usb_desc_configuration *conf, size_t index) {
	size_t cur = 0;
	char *curp = (char *) conf + INTERFACE_DESC_OFFSET;

	while (cur != index) {
		curp += sizeof (struct usb_desc_interface);
		curp += cdc_skip_func_descs(curp);
		curp += cdc_skip_endpoints(curp);
		cur++;
	}

	return (struct usb_desc_interface *) curp;
}

static void cdc_get_endpoints(struct usb_dev *dev, struct usb_class_cdc *cdc) {
	struct usb_desc_endpoint *ep;
	struct usb_desc_interface *iface;
	char *endpoints;
	struct usb_desc_configuration *conf;
	size_t i, j;

	conf = (struct usb_desc_configuration *) cdc->getconf;

	/* TODO conf->b_num_interfaces + 1 must be
	 * conf->b_num_interfaces + alternated settings */
	for (i = 0; i < conf->b_num_interfaces + 1; i++) {
		iface = cdc_get_interface((struct usb_desc_configuration *) cdc->getconf, i);
		endpoints = (char *) iface + sizeof (struct usb_desc_interface);
		endpoints += cdc_skip_func_descs(endpoints);

		for (j = 0; j < iface->b_num_endpoints; j++) {
			ep = (struct usb_desc_endpoint *) endpoints + j;
			assert(usb_endp_alloc(dev, ep));
		}
	}
}

static void cdc_get_conf_hnd(struct usb_request *req, void *arg) {
	struct usb_dev *dev = req->endp->dev;
	struct usb_class_cdc *cdc = usb2cdcdata(dev);
	struct usb_desc_interface *iface;

	iface = cdc_get_interface((struct usb_desc_configuration *) cdc->getconf, 0);

	/* Check if the first interface is one of Microsoft's pet,
	 * and if so then try to skip it. */
	if (is_rndis(iface)) {
		printk("%s\n", "CDC: RNDIS detected");<commit_msg>usb-net: Rewrite skipping of func descs and enpoints<commit_after>/**
 * @file
 * @brief
 *    For more details about configurations and interfaces see
 *    usb specification 1.1 chapter 9.
 *
 * @author  <NAME>
 * @date    05.04.2014
 */

#include <mem/misc/pool.h>
#include <mem/sysmalloc.h>
#include <kernel/printk.h>
#include <kernel/panic.h>
#include <embox/unit.h>
#include <drivers/usb/usb_cdc.h>
#include <drivers/usb/usb_driver.h>
#include <kernel/printk.h>
#include <stdlib.h>
#include <string.h>

EMBOX_UNIT_INIT(usb_cdc_init);

POOL_DEF(cdc_classes, struct usb_class_cdc, USB_CDC_MAX_DEVS);

/* Storage for device configuration*/
static char cdc_conf[16];

#define INTERFACE_DESC_OFFSET          (sizeof (struct usb_desc_configuration))
#define CS_INTERFACE                   0x24

/* Configuration */
static void cdc_get_conf_len_hnd(struct usb_request *req, void *arg);
static void cdc_get_conf(struct usb_dev *dev, struct usb_class_cdc *cdc,
		size_t idx, size_t len, usb_request_notify_hnd_t cb);
static void cdc_get_conf_content_hnd(struct usb_request *req, void *arg);
static void cdc_get_conf_hnd(struct usb_request *req, void *arg);
static void cdc_next_conf(struct usb_dev *dev);

/* Endpoint */
static void cdc_get_endpoints(struct usb_dev *dev, struct usb_class_cdc *cdc);

/* Misc */
static size_t cdc_skip_type(uint8_t *start, uint8_t skip_type);
static int is_rndis(struct usb_desc_interface *desc);


/**
 * Skip all functional descriptors or all endpoints.
 * Return size of all skipped elements.
 * @see ecm120.pdf (Subclass Specification for
 *  Ethernet Control Model Devices) Section 5
 */
static size_t cdc_skip_type(uint8_t *start, uint8_t skip_type) {
	uint8_t *cur = start;

	while (cur[1] == skip_type) {
		uint8_t len = *cur;
		cur += len;
	}

	return (cur - start);
}


struct usb_desc_interface *cdc_get_interface(
		struct usb_desc_configuration *conf, size_t index) {
	size_t cur = 0;
	char *curp = (char *) conf + INTERFACE_DESC_OFFSET;

	while (cur != index) {
		curp += sizeof (struct usb_desc_interface);
		curp += cdc_skip_type((uint8_t*) curp, CS_INTERFACE);
		curp += cdc_skip_type((uint8_t*) curp, USB_DESC_TYPE_ENDPOINT);
		cur++;
	}

	return (struct usb_desc_interface *) curp;
}

static void cdc_get_endpoints(struct usb_dev *dev, struct usb_class_cdc *cdc) {
	struct usb_desc_endpoint *ep;
	struct usb_desc_interface *iface;
	char *endpoints;
	struct usb_desc_configuration *conf;
	size_t i, j;

	conf = (struct usb_desc_configuration *) cdc->getconf;

	/* TODO conf->b_num_interfaces + 1 must be
	 * conf->b_num_interfaces + alternated settings */
	for (i = 0; i < conf->b_num_interfaces + 1; i++) {
		iface = cdc_get_interface((struct usb_desc_configuration *) cdc->getconf, i);
		endpoints = (char *) iface + sizeof (struct usb_desc_interface);
		endpoints += cdc_skip_type((uint8_t*)endpoints, CS_INTERFACE);

		for (j = 0; j < iface->b_num_endpoints; j++) {
			ep = (struct usb_desc_endpoint *) endpoints + j;
			assert(usb_endp_alloc(dev, ep));
		}
	}
}

static void cdc_get_conf_hnd(struct usb_request *req, void *arg) {
	struct usb_dev *dev = req->endp->dev;
	struct usb_class_cdc *cdc = usb2cdcdata(dev);
	struct usb_desc_interface *iface;

	iface = cdc_get_interface((struct usb_desc_configuration *) cdc->getconf, 0);

	/* Check if the first interface is one of Microsoft's pet,
	 * and if so then try to skip it. */
	if (is_rndis(iface)) {
		printk("%s\n", "CDC: RNDIS detected");
{'fraction_non_alphanumeric': 0.11792129439188263, 'fraction_numerical': 0.01014671602906897, 'mean_word_length': 4.555217060167555, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6255252', 'n_tokens_mistral': 2814, 'n_tokens_neox': 2662, 'n_words': 694}