Exemplo n.º 1
0
struct io *
connectio(
    struct server *srv, int verify, const char *eol, int timeout, char **cause)
{
	int		 fd = -1, error = 0;
	struct addrinfo	 hints;
	struct addrinfo	*ai;
	const char	*fn = NULL;
	SSL		*ssl;

	if (srv->ai == NULL) {
		memset(&hints, 0, sizeof hints);
		hints.ai_family = PF_UNSPEC;
		hints.ai_socktype = SOCK_STREAM;
		error = getaddrinfo(srv->host, srv->port, &hints, &srv->ai);
		if (error != 0) {
			*cause = xstrdup(gai_strerror(error));
			return (NULL);
		}
	}

	for (ai = srv->ai; ai != NULL; ai = ai->ai_next) {
	retry:
		fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
		if (fd < 0) {
			fn = "socket";
			continue;
		}
		if (connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
			error = errno;
			close(fd);
			errno = error;
			if (errno == EINTR)
				goto retry;
			fd = -1;
			fn = "connect";
			continue;
		}
		break;
	}

	if (fd < 0) {
		xasprintf(cause, "%s: %s", fn, strerror(errno));
		return (NULL);
	}
	if (!srv->ssl)
		return (io_create(fd, NULL, eol));

	ssl = makessl(srv, fd, verify && srv->verify, timeout, cause);
	if (ssl == NULL) {
		close(fd);
		return (NULL);
	}
	return (io_create(fd, ssl, eol));
}
Exemplo n.º 2
0
int io_mem_create(char *buf, size_t size, int flags, io_t **pio)
{
    io_mem_t *im = NULL;

    dbg_err_if (buf == NULL);
    dbg_err_if (pio == NULL);
    
    dbg_err_if(io_create(io_mem_t, (io_t**)&im));

    im->io.type = IO_TYPE_MEM;

    im->buf = buf;
    im->size = size;
    im->flags = flags;
    im->off = 0;
    im->io.read = (io_read_op) io_mem_read;
    im->io.write = (io_write_op) io_mem_write;
    im->io.seek = (io_seek_op) io_mem_seek;
    im->io.tell = (io_tell_op) io_mem_tell;
    im->io.close = (io_close_op) io_mem_close; 
    im->io.free = (io_free_op) io_mem_free; 

    *pio = (io_t*)im;

    return 0;
err:
    if(im)
        io_free((io_t *)im);
    return ~0;
}
Exemplo n.º 3
0
static void _tcp_accept(uv_stream_t *master, int status, bool tls)
{
	if (status != 0) {
		return;
	}
	uv_stream_t *client = handle_alloc(master->loop);
	if (!client) {
		return;
	}
	memset(client, 0, sizeof(*client));
	io_create(master->loop, (uv_handle_t *)client, SOCK_STREAM);
	if (uv_accept(master, client) != 0) {
		uv_close((uv_handle_t *)client, io_free);
		return;
	}

	/* Set deadlines for TCP connection and start reading.
	 * It will re-check every half of a request time limit if the connection
	 * is idle and should be terminated, this is an educated guess. */
	struct session *session = client->data;
	session->has_tls = tls;
	if (tls && !session->tls_ctx) {
		session->tls_ctx = tls_new(master->loop->data);
	}
	uv_timer_t *timer = &session->timeout;
	uv_timer_init(master->loop, timer);
	timer->data = client;
	uv_timer_start(timer, tcp_timeout_trigger, KR_CONN_RTT_MAX/2, KR_CONN_RTT_MAX/2);
	io_start_read((uv_handle_t *)client);
}
Exemplo n.º 4
0
void vfss_resize_buf(VFSS_TYPE* vfss, unsigned int size)
{
    if (size > vfss->io_size)
    {
        io_destroy(vfss->io);
        vfss->io = io_create(size + sizeof(STORAGE_STACK));
        vfss->io_size = size;
    }
}
Exemplo n.º 5
0
static void init(LORA* lora)
{
    memset(lora, 0, sizeof(LORA));
    lora->spi.io = io_create(LORA_SPI_IO_SIZE);
    lora->timer_txrx_timeout = timer_create(LORA_TIMER_TXRX_TIMEOUT_ID, HAL_LORA);
    lora->timer_poll_timeout = timer_create(LORA_TIMER_POLL_TIMEOUT_ID, HAL_LORA);
    lora->opened = false;
    lora->sys_vars = NULL;
}
Exemplo n.º 6
0
void rndis_set_vendor_description(HANDLE usbd, unsigned int iface, const char* vendor)
{
    IO* io;
    unsigned int size = strlen(vendor) + 1;
    io = io_create(size);
    strcpy(io_data(io), vendor);
    io->data_size = size;
    io_write_sync(usbd, HAL_IO_REQ(HAL_USBD_IFACE, RNDIS_SET_VENDOR_DESCRIPTION), iface, io);
    io_destroy(io);
}
Exemplo n.º 7
0
void hidd_kbd_class_configured(USBD* usbd, USB_CONFIGURATION_DESCRIPTOR* cfg)
{
    USB_INTERFACE_DESCRIPTOR* iface;
    USB_ENDPOINT_DESCRIPTOR* ep;
    uint8_t in_ep, hid_iface;
    unsigned in_ep_size;
    in_ep = in_ep_size = hid_iface = 0;

    //check control/data ep here
    for (iface = usb_get_first_interface(cfg); iface != NULL; iface = usb_get_next_interface(cfg, iface))
    {
        if (iface->bInterfaceClass == HID_INTERFACE_CLASS && iface->bInterfaceSubClass == HID_SUBCLASS_BOOT_INTERFACE &&
            iface->bInterfaceProtocol == HID_PROTOCOL_KEYBOARD)
        {
            ep = (USB_ENDPOINT_DESCRIPTOR*)usb_interface_get_first_descriptor(cfg, iface, USB_ENDPOINT_DESCRIPTOR_TYPE);
            if (ep != NULL)
            {
                in_ep = USB_EP_NUM(ep->bEndpointAddress);
                in_ep_size = ep->wMaxPacketSize;
                hid_iface = iface->bInterfaceNumber;
                break;
            }
        }
    }

    //No HID descriptors in interface
    if (in_ep == 0)
        return;
    HIDD_KBD* hidd = (HIDD_KBD*)malloc(sizeof(HIDD_KBD));
    if (hidd == NULL)
        return;
    hidd->io = io_create(in_ep_size);

    if (hidd->io == NULL)
    {
        hidd_kbd_destroy(hidd);
        return;
    }
    hidd->iface = hid_iface;
    hidd->in_ep = in_ep;
    hidd->suspended = false;
    hidd->over = false;
    hidd->idle = 0;
    hidd->boot_protocol = 1;
    hidd->state = USB_HID_KBD_IDLE;
    memset(&hidd->kbd, 0x00, sizeof(BOOT_KEYBOARD));

#if (USBD_HID_DEBUG_REQUESTS)
    printf("Found USB HID device class, EP%d, iface: %d\n", hidd->in_ep, hidd->iface);
#endif //USBD_HID_DEBUG_REQUESTS

    usbd_register_interface(usbd, hidd->iface, &__HIDD_KBD_CLASS, hidd);
    usbd_register_endpoint(usbd, hidd->iface, hidd->in_ep);
    usbd_usb_ep_open(usbd, USB_EP_IN | hidd->in_ep, USB_EP_INTERRUPT, in_ep_size);
}
Exemplo n.º 8
0
static inline void vfss_init(VFSS_TYPE* vfss)
{
    vfss->volume.process = INVALID_HANDLE;
    vfss->io = io_create(FAT_SECTOR_SIZE + sizeof(STORAGE_STACK));
    vfss->io_size = FAT_SECTOR_SIZE;
#if (VFS_BER)
    ber_init(vfss);
#endif //VFS_BER

#if (VFS_NO_FS == 0)
#if (VFS_SFS)
    sfs_init(vfss);
#else
    fat16_init(vfss);
#endif  // VFS_SFS
#endif // VFS_NO_FS
}
Exemplo n.º 9
0
// sets errno on error
int socket_create(Socket *socket) {
	if (io_create(&socket->base, "plain-socket",
	              (IODestroyFunction)socket_destroy,
	              (IOReadFunction)socket_receive,
	              (IOWriteFunction)socket_send) < 0) {
		return -1;
	}

	socket->handle = IO_HANDLE_INVALID;
	socket->family = AF_UNSPEC;
	socket->create_allocated = NULL;
	socket->destroy = socket_destroy_platform;
	socket->receive = socket_receive_platform;
	socket->send = socket_send_platform;

	return 0;
}
Exemplo n.º 10
0
static void tcp_accept(uv_stream_t *master, int status)
{
	if (status != 0) {
		return;
	}

	uv_stream_t *client = handle_alloc(master->loop, sizeof(*client));
	if (!client) {
		return;
	}
	memset(client, 0, sizeof(*client));
	io_create(master->loop, (uv_handle_t *)client, SOCK_STREAM);
	if (uv_accept(master, client) != 0) {
		handle_free((uv_handle_t *)client);
		return;
	}

	io_start_read((uv_handle_t *)client);
}
Exemplo n.º 11
0
/* Fetch mail from stdin. */
int
fetch_stdin_state_mail(struct account *a, struct fetch_ctx *fctx)
{
	struct mail	*m = fctx->mail;
	struct io	*io;
	char		*line, *cause;

	/* Open io for stdin. */
	io = io_create(STDIN_FILENO, NULL, IO_LF);
	if (conf.debug > 3 && !conf.syslog)
		io->dup_fd = STDOUT_FILENO;

	/* Initialise the mail. */
	if (mail_open(m, IO_BLOCKSIZE) != 0) {
		log_warn("%s: failed to create mail", a->name);
		goto error;
	}
	m->size = 0;

	/* Add default tags. */
	default_tags(&m->tags, NULL);

	/* Loop reading the mail. */
	for (;;) {
		/*
		 * There can only be one mail on stdin so reentrancy is
		 * irrelevent. This is a good thing since we want to check for
		 * close which means end of mail.
		 */
		switch (io_pollline2(io,
		    &line, &fctx->lbuf, &fctx->llen, conf.timeout, &cause)) {
		case 0:
			/* Normal close is fine. */
			goto out;
		case -1:
			if (errno == EAGAIN)
				continue;
			log_warnx("%s: %s", a->name, cause);
			xfree(cause);
			goto error;
		}

		if (append_line(m, line, strlen(line)) != 0) {
			log_warn("%s: failed to resize mail", a->name);
			goto error;
		}
		if (m->size > conf.max_size)
			break;
	}

out:
	if (io != NULL)
		io_free(io);

	fctx->state = fetch_stdin_state_exit;
	return (FETCH_MAIL);


error:
	if (io != NULL)
		io_free(io);

	return (FETCH_ERROR);
}
Exemplo n.º 12
0
int create_data(const struct object_descriptor *descr, int size, const void *buffer) {
	return io_create(descr, size, buffer);
}
Exemplo n.º 13
0
void mscd_class_configured(USBD* usbd, USB_CONFIGURATION_DESCRIPTOR* cfg)
{
    USB_INTERFACE_DESCRIPTOR* iface;
    USB_ENDPOINT_DESCRIPTOR* ep;
    void* config;
    int i;
    unsigned int ep_num, ep_size, iface_num, lun_count;
    ep_num = 0;

    //check control/data ep here
    for (iface = usb_get_first_interface(cfg); iface != NULL; iface = usb_get_next_interface(cfg, iface))
    {
        ep = (USB_ENDPOINT_DESCRIPTOR*)usb_interface_get_first_descriptor(cfg, iface, USB_ENDPOINT_DESCRIPTOR_TYPE);
        if (ep != NULL && iface->bInterfaceClass == MSC_INTERFACE_CLASS)
        {
            ep_num = USB_EP_NUM(ep->bEndpointAddress);
            ep_size = ep->wMaxPacketSize;
            iface_num = iface->bInterfaceNumber;
            break;
        }
    }

    //No MSC interface
    if (ep_num == 0)
        return;
    i = usbd_get_cfg(usbd, iface_num);
    config = usbd_get_cfg_data(usbd, i);
    lun_count = 0;
    if (usbd_get_cfg_data_size(usbd, i) > (int)sizeof(uint32_t))
        lun_count = MSC_LUN_COUNT(config);
    if ((config == NULL) || (usbd_get_cfg_data_size(usbd, i) < (int)((sizeof(SCSI_STORAGE_DESCRIPTOR)) * lun_count + sizeof(uint32_t))) || (lun_count == 0))
    {
#if (USBD_MSC_DEBUG_ERRORS)
        printf("MSCD: Failed to read user configuration\n");
#endif //USBD_MSC_DEBUG_ERRORS
        return;
    }
    MSCD* mscd = (MSCD*)malloc(sizeof(MSCD) + sizeof(void*) * lun_count);
    if (mscd == NULL)
        return;

    mscd->iface_num = iface_num;
    mscd->ep_num = ep_num;
    mscd->ep_size = ep_size;
    mscd->usbd = usbd;

    mscd->control = io_create(ep_size);
    mscd->data = io_create(USBD_MSC_IO_SIZE + sizeof(STORAGE_STACK));
    mscd->lun_count = lun_count;
    mscd->io_busy_mask = 0x00000000;
    mscd->io_owner = -1;
    mscd->cbw = io_data(mscd->control);
    for (i = 0; i < mscd->lun_count; ++i)
        MSCD_SCSI(mscd)[i] = scsis_create(mscd_host_cb, mscd, i, MSC_LUN_CONFIGURATION(config, i));
    if (mscd->control == NULL || mscd->data == NULL || MSCD_SCSI(mscd)[mscd->lun_count - 1] == NULL)
    {
#if (USBD_MSC_DEBUG_ERRORS)
        printf("MSCD: Out of memory\n");
#endif //USBD_MSC_DEBUG_ERRORS
        mscd_destroy(mscd);
        return;
    }

    for (i = 0; i < mscd->lun_count; ++i)
        scsis_init(MSCD_SCSI(mscd)[i]);

#if (USBD_MSC_DEBUG_REQUESTS)
    printf("Found USB MSCD class, EP%d, size: %d, iface: %d\n", ep_num, ep_size, iface_num);
#endif //USBD_MSC_DEBUG_REQUESTS

    usbd_register_interface(usbd, iface_num, &__MSCD_CLASS, mscd);
    usbd_register_endpoint(usbd, iface_num, ep_num);

    usbd_usb_ep_open(usbd, USB_EP_IN | ep_num, USB_EP_BULK, ep_size);
    usbd_usb_ep_open(usbd, ep_num, USB_EP_BULK, ep_size);

    mscd_read_cbw(usbd, mscd);
}
Exemplo n.º 14
0
/*
 *  ======== dev_create_device ========
 *  Purpose:
 *      Called by the operating system to load the PM Bridge Driver for a
 *      PM board (device).
 */
int dev_create_device(struct dev_object **device_obj,
			     const char *driver_file_name,
			     struct cfg_devnode *dev_node_obj)
{
	struct cfg_hostres *host_res;
	struct ldr_module *module_obj = NULL;
	struct bridge_drv_interface *drv_fxns = NULL;
	struct dev_object *dev_obj = NULL;
	struct chnl_mgrattrs mgr_attrs;
	struct io_attrs io_mgr_attrs;
	u32 num_windows;
	struct drv_object *hdrv_obj = NULL;
	struct drv_data *drv_datap = dev_get_drvdata(bridge);
	int status = 0;
	DBC_REQUIRE(refs > 0);
	DBC_REQUIRE(device_obj != NULL);
	DBC_REQUIRE(driver_file_name != NULL);

	status = drv_request_bridge_res_dsp((void *)&host_res);

	if (status) {
		dev_dbg(bridge, "%s: Failed to reserve bridge resources\n",
			__func__);
		goto leave;
	}

	/*  Get the Bridge driver interface functions */
	bridge_drv_entry(&drv_fxns, driver_file_name);

	/* Retrieve the Object handle from the driver data */
	if (drv_datap && drv_datap->drv_object) {
		hdrv_obj = drv_datap->drv_object;
	} else {
		status = -EPERM;
		pr_err("%s: Failed to retrieve the object handle\n", __func__);
	}

	/* Create the device object, and pass a handle to the Bridge driver for
	 * storage. */
	if (!status) {
		DBC_ASSERT(drv_fxns);
		dev_obj = kzalloc(sizeof(struct dev_object), GFP_KERNEL);
		if (dev_obj) {
			/* Fill out the rest of the Dev Object structure: */
			dev_obj->dev_node_obj = dev_node_obj;
			dev_obj->module_obj = module_obj;
			dev_obj->cod_mgr = NULL;
			dev_obj->hchnl_mgr = NULL;
			dev_obj->hdeh_mgr = NULL;
			dev_obj->lock_owner = NULL;
			dev_obj->word_size = DSPWORDSIZE;
			dev_obj->hdrv_obj = hdrv_obj;
			dev_obj->dev_type = DSP_UNIT;
			/* Store this Bridge's interface functions, based on its
			 * version. */
			store_interface_fxns(drv_fxns,
						&dev_obj->bridge_interface);

			/* Call fxn_dev_create() to get the Bridge's device
			 * context handle. */
			status = (dev_obj->bridge_interface.pfn_dev_create)
			    (&dev_obj->hbridge_context, dev_obj,
			     host_res);
			/* Assert bridge_dev_create()'s ensure clause: */
			DBC_ASSERT(status
				   || (dev_obj->hbridge_context != NULL));
		} else {
			status = -ENOMEM;
		}
	}
	/* Attempt to create the COD manager for this device: */
	if (!status)
		status = init_cod_mgr(dev_obj);

	/* Attempt to create the channel manager for this device: */
	if (!status) {
		mgr_attrs.max_channels = CHNL_MAXCHANNELS;
		io_mgr_attrs.birq = host_res->birq_registers;
		io_mgr_attrs.irq_shared =
		    (host_res->birq_attrib & CFG_IRQSHARED);
		io_mgr_attrs.word_size = DSPWORDSIZE;
		mgr_attrs.word_size = DSPWORDSIZE;
		num_windows = host_res->num_mem_windows;
		if (num_windows) {
			/* Assume last memory window is for CHNL */
			io_mgr_attrs.shm_base = host_res->dw_mem_base[1] +
			    host_res->dw_offset_for_monitor;
			io_mgr_attrs.usm_length =
			    host_res->dw_mem_length[1] -
			    host_res->dw_offset_for_monitor;
		} else {
			io_mgr_attrs.shm_base = 0;
			io_mgr_attrs.usm_length = 0;
			pr_err("%s: No memory reserved for shared structures\n",
			       __func__);
		}
		status = chnl_create(&dev_obj->hchnl_mgr, dev_obj, &mgr_attrs);
		if (status == -ENOSYS) {
			/* It's OK for a device not to have a channel
			 * manager: */
			status = 0;
		}
		/* Create CMM mgr even if Msg Mgr not impl. */
		status = cmm_create(&dev_obj->hcmm_mgr,
				    (struct dev_object *)dev_obj, NULL);
		/* Only create IO manager if we have a channel manager */
		if (!status && dev_obj->hchnl_mgr) {
			status = io_create(&dev_obj->hio_mgr, dev_obj,
					   &io_mgr_attrs);
		}
		/* Only create DEH manager if we have an IO manager */
		if (!status) {
			/* Instantiate the DEH module */
			status = bridge_deh_create(&dev_obj->hdeh_mgr, dev_obj);
		}
		/* Create DMM mgr . */
		status = dmm_create(&dev_obj->dmm_mgr,
				    (struct dev_object *)dev_obj, NULL);
	}
	/* Add the new DEV_Object to the global list: */
	if (!status) {
		lst_init_elem(&dev_obj->link);
		status = drv_insert_dev_object(hdrv_obj, dev_obj);
	}
	/* Create the Processor List */
	if (!status) {
		dev_obj->proc_list = kzalloc(sizeof(struct lst_list),
							GFP_KERNEL);
		if (!(dev_obj->proc_list))
			status = -EPERM;
		else
			INIT_LIST_HEAD(&dev_obj->proc_list->head);
	}
leave:
	/*  If all went well, return a handle to the dev object;
	 *  else, cleanup and return NULL in the OUT parameter. */
	if (!status) {
		*device_obj = dev_obj;
	} else {
		if (dev_obj) {
			kfree(dev_obj->proc_list);
			if (dev_obj->cod_mgr)
				cod_delete(dev_obj->cod_mgr);
			if (dev_obj->dmm_mgr)
				dmm_destroy(dev_obj->dmm_mgr);
			kfree(dev_obj);
		}

		*device_obj = NULL;
	}

	DBC_ENSURE((!status && *device_obj) || (status && !*device_obj));
	return status;
}
Exemplo n.º 15
0
void cdc_acmd_class_configured(USBD* usbd, USB_CONFIGURATION_DESCRIPTOR* cfg)
{
    USB_INTERFACE_DESCRIPTOR* iface;
    USB_INTERFACE_DESCRIPTOR* diface;
    CDC_UNION_DESCRIPTOR* u;
    USB_ENDPOINT_DESCRIPTOR* ep;
    uint8_t data_ep, data_iface;
    uint16_t data_ep_size;
    uint8_t control_ep, control_iface;
    uint16_t control_ep_size;

    //check control/data ep here
    for (iface = usb_get_first_interface(cfg); iface != NULL; iface = usb_get_next_interface(cfg, iface))
    {
        //also skip RNDIS
        if ((iface->bInterfaceClass != CDC_COMM_INTERFACE_CLASS) || (iface->bInterfaceSubClass != CDC_ACM) || (iface->bInterfaceProtocol == CDC_CP_VENDOR))
            continue;
#if (USBD_CDC_ACM_DEBUG)
        printf("Found USB CDC ACM interface: %d\n", iface->bInterfaceNumber);
#endif //USBD_CDC_ACM_DEBUG
        //find union descriptor
        for (u = usb_interface_get_first_descriptor(cfg, iface, CS_INTERFACE); u != NULL; u = usb_interface_get_next_descriptor(cfg, u, CS_INTERFACE))
        {
            if ((u->bDescriptorSybType == CDC_DESCRIPTOR_UNION) && (u->bControlInterface == iface->bInterfaceNumber) &&
                (u->bFunctionLength > sizeof(CDC_UNION_DESCRIPTOR)))
                break;
        }
        if (u == NULL)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Warning - no UNION descriptor, skipping interface\n");
#endif //USBD_CDC_ACM_DEBUG
            continue;
        }
        data_iface = ((uint8_t*)u)[sizeof(CDC_UNION_DESCRIPTOR)];
        diface = usb_find_interface(cfg, data_iface);
        if (diface == NULL)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Warning no data interface\n");
#endif //USBD_CDC_ACM_DEBUG
            continue;
        }
#if (USBD_CDC_ACM_DEBUG)
        printf("Found USB CDC ACM data interface: %d\n", data_iface);
#endif //USBD_CDC_ACM_DEBUG

        ep = (USB_ENDPOINT_DESCRIPTOR*)usb_interface_get_first_descriptor(cfg, diface, USB_ENDPOINT_DESCRIPTOR_TYPE);
        if (ep == NULL)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Warning no data EP, skipping interface\n");
#endif //USBD_CDC_ACM_DEBUG
            continue;
        }
        data_ep = USB_EP_NUM(ep->bEndpointAddress);
        data_ep_size = ep->wMaxPacketSize;

        control_iface = iface->bInterfaceNumber;
        control_ep = control_ep_size = 0;
        ep = (USB_ENDPOINT_DESCRIPTOR*)usb_interface_get_first_descriptor(cfg, iface, USB_ENDPOINT_DESCRIPTOR_TYPE);
        if (ep != NULL)
        {
            control_ep = USB_EP_NUM(ep->bEndpointAddress);
            control_ep_size = ep->wMaxPacketSize;
        }

        //configuration is ok, applying
        CDC_ACMD* cdc_acmd = (CDC_ACMD*)malloc(sizeof(CDC_ACMD));
        if (cdc_acmd == NULL)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Out of memory\n");
#endif //USBD_CDC_ACM_DEBUG
            return;
        }

        cdc_acmd->data_iface = data_iface;
        cdc_acmd->data_ep = data_ep;
        cdc_acmd->data_ep_size = data_ep_size;
        cdc_acmd->tx = cdc_acmd->rx = NULL;
        cdc_acmd->tx_stream = cdc_acmd->rx_stream = cdc_acmd->tx_stream_handle = cdc_acmd->rx_stream_handle = INVALID_HANDLE;
        cdc_acmd->suspended = false;

        cdc_acmd->control_iface = control_iface;
        cdc_acmd->control_ep = control_ep;
        cdc_acmd->control_ep_size = control_ep_size;
        cdc_acmd->notify = NULL;
        cdc_acmd->notify_busy = cdc_acmd->notify_pending = false;
#if (USBD_CDC_ACM_FLOW_CONTROL)
        cdc_acmd->flow_sending = false;
        cdc_acmd->flow_changed = false;
        cdc_acmd->break_count = 0;
#endif //USBD_CDC_ACM_FLOW_CONTROL

#if (USBD_CDC_ACM_TX_STREAM_SIZE)
        cdc_acmd->tx = io_create(cdc_acmd->data_ep_size);
        cdc_acmd->tx_stream = stream_create(USBD_CDC_ACM_RX_STREAM_SIZE);
        cdc_acmd->tx_stream_handle = stream_open(cdc_acmd->tx_stream);
        if (cdc_acmd->tx == NULL || cdc_acmd->tx_stream_handle == INVALID_HANDLE)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Out of memory\n");
#endif //USBD_CDC_ACM_DEBUG
            cdc_acmd_destroy(cdc_acmd);
            return;
        }
        cdc_acmd->tx_size = 0;
        cdc_acmd->tx_idle = true;
        usbd_usb_ep_open(usbd, USB_EP_IN | cdc_acmd->data_ep, USB_EP_BULK, cdc_acmd->data_ep_size);
        stream_listen(cdc_acmd->tx_stream, USBD_IFACE(cdc_acmd->data_iface, 0), HAL_USBD_IFACE);
#endif //USBD_CDC_ACM_TX_STREAM_SIZE

#if (USBD_CDC_ACM_RX_STREAM_SIZE)
        cdc_acmd->rx = io_create(cdc_acmd->data_ep_size);
        cdc_acmd->rx_stream = stream_create(USBD_CDC_ACM_RX_STREAM_SIZE);
        cdc_acmd->rx_stream_handle = stream_open(cdc_acmd->rx_stream);
        if (cdc_acmd->rx == NULL || cdc_acmd->rx_stream_handle == INVALID_HANDLE)
        {
#if (USBD_CDC_ACM_DEBUG)
            printf("USB CDC ACM: Out of memory\n");
#endif //USBD_CDC_ACM_DEBUG
            cdc_acmd_destroy(cdc_acmd);
            return;
        }
        cdc_acmd->rx_free = 0;
        usbd_usb_ep_open(usbd, cdc_acmd->data_ep, USB_EP_BULK, cdc_acmd->data_ep_size);
        usbd_usb_ep_read(usbd, cdc_acmd->data_ep, cdc_acmd->rx, cdc_acmd->data_ep_size);
#endif //USBD_CDC_ACM_RX_STREAM_SIZE

        usbd_register_interface(usbd, cdc_acmd->data_iface, &__CDC_ACMD_CLASS, cdc_acmd);
        usbd_register_endpoint(usbd, cdc_acmd->data_iface, cdc_acmd->data_ep);

        if (control_ep_size)
        {
            if (cdc_acmd->control_ep_size < 16)
            {
#if (USBD_CDC_ACM_DEBUG)
                printf("USB CDC ACM: Warning - control endpoint is too small(%d), 16 at least required to fit notify", cdc_acmd->control_ep_size);
#endif //USBD_CDC_ACM_DEBUG
                cdc_acmd->notify = io_create(16);
            }
            else
                cdc_acmd->notify = io_create(cdc_acmd->control_ep_size);
            if (cdc_acmd->notify == NULL)
            {
                cdc_acmd_destroy(cdc_acmd);
                return;
            }
            usbd_usb_ep_open(usbd, USB_EP_IN | cdc_acmd->control_ep, USB_EP_INTERRUPT, cdc_acmd->control_ep_size);
            usbd_register_interface(usbd, cdc_acmd->control_iface, &__CDC_ACMD_CLASS, cdc_acmd);
            usbd_register_endpoint(usbd, cdc_acmd->control_iface, cdc_acmd->control_ep);
            cdc_acmd_notify_serial_state(usbd, cdc_acmd, CDC_SERIAL_STATE_DCD | CDC_SERIAL_STATE_DSR);
        }
        cdc_acmd->DTR = cdc_acmd->RTS = false;
        cdc_acmd->baud.baud = 115200;
        cdc_acmd->baud.data_bits = 8;
        cdc_acmd->baud.parity = 'N';
        cdc_acmd->baud.stop_bits = 1;
    }
}