Ejemplo n.º 1
0
Archivo: uhi_cdc.c Proyecto: marekr/asf
void uhi_cdc_uninstall(uhc_device_t* dev)
{
	if (uhi_cdc_dev.dev != dev) {
		return; // Device not enabled in this interface
	}
	uhi_cdc_dev.dev = NULL;
	uhi_cdc_free_device();
	UHI_CDC_CHANGE(dev,false);
}
Ejemplo n.º 2
0
Archivo: uhi_cdc.c Proyecto: marekr/asf
uhc_enum_status_t uhi_cdc_install(uhc_device_t* dev)
{
	bool b_iface_comm, b_iface_data;
	uint16_t conf_desc_lgt;
	uint8_t port_num, i;
	usb_iface_desc_t *ptr_iface;
	uhi_cdc_port_t *ptr_port = NULL;
	uhi_cdc_line_t *ptr_line;

	if (uhi_cdc_dev.dev != NULL) {
		return UHC_ENUM_SOFTWARE_LIMIT; // Device already allocated
	}

	// Compute the number of port
	conf_desc_lgt = le16_to_cpu(dev->conf_desc->wTotalLength);
	ptr_iface = (usb_iface_desc_t*)dev->conf_desc;
	uhi_cdc_dev.nb_port = 0;
	while (conf_desc_lgt) {
		if ((ptr_iface->bDescriptorType == USB_DT_INTERFACE)
				&& (ptr_iface->bInterfaceClass == CDC_CLASS_COMM)
				&& (ptr_iface->bInterfaceSubClass == CDC_SUBCLASS_ACM)
				&& (ptr_iface->bInterfaceProtocol <= CDC_PROTOCOL_V25TER)) {
			// New COM port has been found
			uhi_cdc_dev.nb_port++;
		}
		Assert(conf_desc_lgt>=ptr_iface->bLength);
		conf_desc_lgt -= ptr_iface->bLength;
		ptr_iface = (usb_iface_desc_t*)((uint8_t*)ptr_iface + ptr_iface->bLength);
	}
	if (uhi_cdc_dev.nb_port == 0) {
		return UHC_ENUM_UNSUPPORTED; // No interface supported
	}

	// Alloc port structures
	uhi_cdc_dev.port = malloc(uhi_cdc_dev.nb_port * sizeof(uhi_cdc_port_t));
	if (uhi_cdc_dev.port == NULL) {
		Assert(false);
		return UHC_ENUM_SOFTWARE_LIMIT;
	}
	// Initialize structure
	for (i = 0; i<uhi_cdc_dev.nb_port; i++) {
		uhi_cdc_dev.port[i].ep_comm_in = 0;
		uhi_cdc_dev.port[i].iface_data = 0xFF;
		uhi_cdc_dev.port[i].line_rx.ep_data = 0;
		uhi_cdc_dev.port[i].line_rx.buffer[0].ptr = NULL;
		uhi_cdc_dev.port[i].line_rx.buffer[1].ptr = NULL;
		uhi_cdc_dev.port[i].line_tx.ep_data = 0;
		uhi_cdc_dev.port[i].line_tx.buffer[0].ptr = NULL;
		uhi_cdc_dev.port[i].line_tx.buffer[1].ptr = NULL;
	}

	// Fill port structures
	conf_desc_lgt = le16_to_cpu(dev->conf_desc->wTotalLength);
	ptr_iface = (usb_iface_desc_t*)dev->conf_desc;
	b_iface_comm = false;
	b_iface_data = false;
	port_num = 0;
	while (conf_desc_lgt) {
		switch (ptr_iface->bDescriptorType) {

		case USB_DT_INTERFACE:
			if ((ptr_iface->bInterfaceClass == CDC_CLASS_COMM)
					&& (ptr_iface->bInterfaceSubClass == CDC_SUBCLASS_ACM)
					&& (ptr_iface->bInterfaceProtocol <= CDC_PROTOCOL_V25TER) ) {
				// New Communication Class COM port has been found
				b_iface_comm = true;
				ptr_port = &uhi_cdc_dev.port[port_num++];
				ptr_port->iface_comm = ptr_iface->bInterfaceNumber;
			} else {
				// Stop allocation endpoint(s)
				b_iface_comm = false;
			}
			if ((ptr_iface->bInterfaceClass == CDC_CLASS_DATA)
					&& (ptr_iface->bInterfaceSubClass == 0)
					&& (ptr_iface->bInterfaceProtocol == 0) ) {
				for (i = 0; i<uhi_cdc_dev.nb_port; i++) {
					ptr_port = &uhi_cdc_dev.port[i];
					if (ptr_port->iface_data == 0xFF) {
						b_iface_data = true;
						break;
					}
					else if (ptr_port->iface_data == ptr_iface->bInterfaceNumber) {
						// New CDC DATA Class has been found
						// and correspond at a CDC COMM Class
						b_iface_data = true;
						break;
					}
				}
			} else {
				// Stop allocation endpoint(s)
				b_iface_data = false;
			}
			break;

		case CDC_CS_INTERFACE:
			if (!b_iface_comm) {
				break;
			}
			if (((usb_cdc_call_mgmt_desc_t*)ptr_iface)->bDescriptorSubtype == CDC_SCS_CALL_MGMT) {
				ptr_port->iface_data = ((usb_cdc_call_mgmt_desc_t*)ptr_iface)->bDataInterface;
			}
			break;

		case USB_DT_ENDPOINT:
			//  Allocation of the endpoint
			if (b_iface_comm) {
				Assert ((usb_ep_desc_t*)ptr_iface->bmAttributes == USB_EP_TYPE_INTERRUPT);
				Assert ((usb_ep_desc_t*)ptr_iface->bEndpointAddress & USB_EP_DIR_IN);
				if (!uhd_ep_alloc(dev->address, (usb_ep_desc_t*)ptr_iface)) {
					uhi_cdc_free_device();
					return UHC_ENUM_HARDWARE_LIMIT; // Endpoint allocation fail
				}
				ptr_port->ep_comm_in = ((usb_ep_desc_t*)ptr_iface)->bEndpointAddress;
			}
			if (b_iface_data) {
				Assert (((usb_ep_desc_t*)ptr_iface)->bmAttributes == USB_EP_TYPE_BULK);
				if (!uhd_ep_alloc(dev->address, (usb_ep_desc_t*)ptr_iface)) {
					uhi_cdc_free_device();
					return UHC_ENUM_HARDWARE_LIMIT; // Endpoint allocation fail
				}

				if (((usb_ep_desc_t*)ptr_iface)->bEndpointAddress & USB_EP_DIR_IN) {
					ptr_line = &ptr_port->line_rx;
				} else {
					ptr_line = &ptr_port->line_tx;
				}
				ptr_line->ep_data = ((usb_ep_desc_t*)ptr_iface)->bEndpointAddress;
				ptr_line->b_trans_ongoing = false;
				ptr_line->buf_sel = 0;

				// Allocate and initialize buffers
				uint16_t buf_size = Max( le16_to_cpu(
						((usb_ep_desc_t*)ptr_iface)->wMaxPacketSize),
						UHI_CDC_BUFFER_SIZE );
				ptr_line->buffer_size = buf_size;
				ptr_line->buffer[0].pos = 0;
				ptr_line->buffer[0].nb = 0;
				ptr_line->buffer[0].ptr = malloc(buf_size);
				if (ptr_line->buffer[0].ptr == NULL) {
					Assert(false);
					uhi_cdc_free_device();
					return UHC_ENUM_SOFTWARE_LIMIT;
				}
				ptr_line->buffer[1].pos = 0;
				ptr_line->buffer[1].nb = 0;
				ptr_line->buffer[1].ptr = malloc(buf_size);
				if (ptr_line->buffer[1].ptr == NULL) {
					Assert(false);
					uhi_cdc_free_device();
					return UHC_ENUM_SOFTWARE_LIMIT;
				}

			}
			break;

		}
		Assert(conf_desc_lgt >= ptr_iface->bLength);
		conf_desc_lgt -= ptr_iface->bLength;
		ptr_iface = (usb_iface_desc_t*)((uint8_t*)ptr_iface + ptr_iface->bLength);
	}

	// Check installed ports
	for (i = 0; i<uhi_cdc_dev.nb_port; i++) {
		if ((uhi_cdc_dev.port[i].ep_comm_in == 0)
				|| (uhi_cdc_dev.port[i].line_rx.ep_data == 0)
				|| (uhi_cdc_dev.port[i].line_tx.ep_data == 0)) {
			// Install is not complete
			uhi_cdc_free_device();
			return UHC_ENUM_UNSUPPORTED;
		}
	}
	uhi_cdc_dev.b_enabled = false;
	uhi_cdc_dev.dev = dev;
	return UHC_ENUM_SUCCESS;
}
Ejemplo n.º 3
0
Archivo: uhi_cdc.c Proyecto: gstroe/Arm
USBH_enum_status_t uhi_cdc_install(USBH_device_t *dev)
{
	bool b_iface_comm, b_iface_data;
	uint16_t conf_desc_lgt;
	uint8_t port_num, i;
	USBInterfaceDescriptor *ptr_iface;
	uhi_cdc_port_t *ptr_port = NULL;
	uhi_cdc_line_t *ptr_line;

	if (uhi_cdc_dev.dev != NULL) {
		return UHC_ENUM_SOFTWARE_LIMIT; // Device already allocated
	}

	// Compute the number of port
	conf_desc_lgt = (dev->conf_desc->wTotalLength);
	ptr_iface = (USBInterfaceDescriptor *)dev->conf_desc;
	uhi_cdc_dev.nb_port = 0;

	while (conf_desc_lgt) {
		if ((ptr_iface->bDescriptorType == USBGenericDescriptor_INTERFACE)
			&& (ptr_iface->bInterfaceClass == CDCCommunicationInterfaceDescriptor_CLASS)
			&& (ptr_iface->bInterfaceSubClass ==
				CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL)
			&& (ptr_iface->bInterfaceProtocol <=
				CDCCommunicationInterfaceDescriptor_NOPROTOCOL)) {
			// New COM port has been found
			uhi_cdc_dev.nb_port++;
		}

		assert(conf_desc_lgt >= ptr_iface->bLength);
		conf_desc_lgt -= ptr_iface->bLength;
		ptr_iface = (USBInterfaceDescriptor *)((uint8_t *)ptr_iface +
											   ptr_iface->bLength);
	}

	if (uhi_cdc_dev.nb_port == 0) {
		return UHC_ENUM_UNSUPPORTED; // No interface supported
	}

	// Alloc port structures
	uhi_cdc_dev.port = malloc(uhi_cdc_dev.nb_port * sizeof(uhi_cdc_port_t));

	if (uhi_cdc_dev.port == NULL) {
		assert(false);
		return UHC_ENUM_SOFTWARE_LIMIT;
	}

	// Initialize structure
	for (i = 0; i < uhi_cdc_dev.nb_port; i++) {
		uhi_cdc_dev.port[i].ep_comm_in = 0;
		uhi_cdc_dev.port[i].iface_data = 0xFF;
		uhi_cdc_dev.port[i].line_rx.ep_data = 0;
		uhi_cdc_dev.port[i].line_rx.buffer[0].ptr = NULL;
		uhi_cdc_dev.port[i].line_rx.buffer[1].ptr = NULL;
		uhi_cdc_dev.port[i].line_tx.ep_data = 0;
		uhi_cdc_dev.port[i].line_tx.buffer[0].ptr = NULL;
		uhi_cdc_dev.port[i].line_tx.buffer[1].ptr = NULL;
	}

	// Fill port structures
	conf_desc_lgt = (dev->conf_desc->wTotalLength);
	ptr_iface = (USBInterfaceDescriptor *)dev->conf_desc;
	b_iface_comm = false;
	b_iface_data = false;
	port_num = 0;

	while (conf_desc_lgt) {
		switch (ptr_iface->bDescriptorType) {

		case USBGenericDescriptor_INTERFACE:
			if ((ptr_iface->bInterfaceClass == CDCCommunicationInterfaceDescriptor_CLASS)
				&& (ptr_iface->bInterfaceSubClass ==
					CDCCommunicationInterfaceDescriptor_ABSTRACTCONTROLMODEL)
				&& (ptr_iface->bInterfaceProtocol <=
					CDCCommunicationInterfaceDescriptor_NOPROTOCOL)) {
				// New Communication Class COM port has been found
				b_iface_comm = true;
				ptr_port = &uhi_cdc_dev.port[port_num++];
				ptr_port->iface_comm = ptr_iface->bInterfaceNumber;
			} else {
				// Stop allocation endpoint(s)
				b_iface_comm = false;
			}

			if ((ptr_iface->bInterfaceClass == CDCDataInterfaceDescriptor_CLASS)
				&& (ptr_iface->bInterfaceSubClass == 0)
				&& (ptr_iface->bInterfaceProtocol == 0)) {
				for (i = 0; i < uhi_cdc_dev.nb_port; i++) {
					ptr_port = &uhi_cdc_dev.port[i];
					b_iface_data = true;
					break;
				}
			} else {
				// Stop allocation endpoint(s)
				b_iface_data = false;
			}

			break;

		case CDCGenericDescriptor_INTERFACE:
			if (!b_iface_comm)
				break;

			if (((CDCCallManagementDescriptor *)ptr_iface)->bDescriptorSubtype ==
				CDCGenericDescriptor_CALLMANAGEMENT)
				ptr_port->iface_data = ((CDCCallManagementDescriptor *)
										ptr_iface)->bDataInterface;

			break;

		case USBGenericDescriptor_ENDPOINT:

			//  Allocation of the endpoint
			if (b_iface_comm) {
				assert (((USBEndpointDescriptor *)ptr_iface)->bmAttributes ==
						USBEndpointDescriptor_INTERRUPT);
				assert(((USBEndpointDescriptor *)ptr_iface)->bEndpointAddress & USB_EP_DIR_IN);

				if (!USBH_HAL_ConfigurePipe(dev->address, (USBEndpointDescriptor *)ptr_iface)) {
					uhi_cdc_free_device();
					return UHC_ENUM_HARDWARE_LIMIT; // Endpoint allocation fail
				}

				ptr_port->ep_comm_in = ((USBEndpointDescriptor *)ptr_iface)->bEndpointAddress;
			}

			if (b_iface_data) {
				assert (((USBEndpointDescriptor *)ptr_iface)->bmAttributes ==
						USBEndpointDescriptor_BULK);

				if (!USBH_HAL_ConfigurePipe(dev->address, (USBEndpointDescriptor *)ptr_iface)) {
					uhi_cdc_free_device();
					return UHC_ENUM_HARDWARE_LIMIT; // Endpoint allocation fail
				}

				if (((USBEndpointDescriptor *)ptr_iface)->bEndpointAddress & USB_EP_DIR_IN)
					ptr_line = &ptr_port->line_rx;
				else
					ptr_line = &ptr_port->line_tx;

				ptr_line->ep_data = ((USBEndpointDescriptor *)ptr_iface)->bEndpointAddress;
				ptr_line->b_trans_ongoing = false;
				ptr_line->buf_sel = 0;

				// Allocate and initialize buffers
				uint16_t buf_size = Max((
											 ((USBEndpointDescriptor *)ptr_iface)->wMaxPacketSize),
										 UHI_CDC_BUFFER_SIZE);
				ptr_line->buffer_size = buf_size;
				ptr_line->buffer[0].pos = 0;
				ptr_line->buffer[0].nb = 0;
				ptr_line->buffer[0].ptr = malloc(buf_size);

				if (ptr_line->buffer[0].ptr == NULL) {
					assert(false);
					uhi_cdc_free_device();
					return UHC_ENUM_SOFTWARE_LIMIT;
				}

				ptr_line->buffer[1].pos = 0;
				ptr_line->buffer[1].nb = 0;
				ptr_line->buffer[1].ptr = malloc(buf_size);

				if (ptr_line->buffer[1].ptr == NULL) {
					assert(false);
					uhi_cdc_free_device();
					return UHC_ENUM_SOFTWARE_LIMIT;
				}

			}

			break;

		}

		assert(conf_desc_lgt >= ptr_iface->bLength);
		conf_desc_lgt -= ptr_iface->bLength;
		ptr_iface = (USBInterfaceDescriptor *)((uint8_t *)ptr_iface +
											   ptr_iface->bLength);
	}

	// Check installed ports
	for (i = 0; i < uhi_cdc_dev.nb_port; i++) {
		if ((uhi_cdc_dev.port[i].ep_comm_in == 0)
			|| (uhi_cdc_dev.port[i].line_rx.ep_data == 0)
			|| (uhi_cdc_dev.port[i].line_tx.ep_data == 0)) {
			// Install is not complete
			uhi_cdc_free_device();
			return UHC_ENUM_UNSUPPORTED;
		}
	}

	uhi_cdc_dev.b_enabled = false;
	uhi_cdc_dev.dev = dev;
	return UHC_ENUM_SUCCESS;
}