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); }
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; }
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; }