/* Due to the difference of HS and FS descriptors, the device descriptors and configurations need to be updated to match * current speed. * As the default, the device descriptors and configurations are configured by using FS parameters for both EHCI and * KHCI. * When the EHCI is enabled, the application needs to call this fucntion to update device by using current speed. * The updated information includes endpoint max packet size, endpoint interval, etc. */ usb_status_t USB_DeviceSetSpeed(uint8_t speed) { usb_descriptor_union_t *descriptorHead; usb_descriptor_union_t *descriptorTail; descriptorHead = (usb_descriptor_union_t *)&g_UsbDeviceConfigurationDescriptor[0]; descriptorTail = (usb_descriptor_union_t *)(&g_UsbDeviceConfigurationDescriptor[USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL - 1U]); while (descriptorHead < descriptorTail) { if (descriptorHead->common.bDescriptorType == USB_DESCRIPTOR_TYPE_ENDPOINT) { if (USB_SPEED_HIGH == speed) { if (USB_VIDEO_VIRTUAL_CAMERA_STREAM_ENDPOINT_IN == (descriptorHead->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)) { descriptorHead->endpoint.bInterval = HS_STREAM_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_STREAM_IN_PACKET_SIZE, descriptorHead->endpoint.wMaxPacketSize); } else { descriptorHead->endpoint.bInterval = HS_INTERRUPT_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_INTERRUPT_IN_PACKET_SIZE, descriptorHead->endpoint.wMaxPacketSize); } } else { if (USB_VIDEO_VIRTUAL_CAMERA_STREAM_ENDPOINT_IN == (descriptorHead->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK)) { descriptorHead->endpoint.bInterval = FS_STREAM_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_STREAM_IN_PACKET_SIZE, descriptorHead->endpoint.wMaxPacketSize); } else { descriptorHead->endpoint.bInterval = FS_INTERRUPT_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_INTERRUPT_IN_PACKET_SIZE, descriptorHead->endpoint.wMaxPacketSize); } } } descriptorHead = (usb_descriptor_union_t *)((uint8_t *)descriptorHead + descriptorHead->common.bLength); } return kStatus_USB_Success; }
/* Due to the difference of HS and FS descriptors, the device descriptors and configurations need to be updated to match * current speed. * As the default, the device descriptors and configurations are configured by using FS parameters for both EHCI and * KHCI. * When the EHCI is enabled, the application needs to call this fucntion to update device by using current speed. * The updated information includes endpoint max packet size, endpoint interval, etc. */ usb_status_t USB_DeviceSetSpeed(usb_device_handle handle, uint8_t speed) { usb_descriptor_union_t *descriptorHead; usb_descriptor_union_t *descriptorTail; descriptorHead = (usb_descriptor_union_t *)&g_UsbDeviceConfigurationDescriptor[0]; descriptorTail = (usb_descriptor_union_t *)(&g_UsbDeviceConfigurationDescriptor[USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL - 1U]); while (descriptorHead < descriptorTail) { if (descriptorHead->common.bDescriptorType == USB_DESCRIPTOR_TYPE_ENDPOINT) { if (USB_SPEED_HIGH == speed) { if (((descriptorHead->endpoint.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) == USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && (USB_HID_MOUSE_ENDPOINT_IN == (descriptorHead->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))) { descriptorHead->endpoint.bInterval = HS_HID_MOUSE_INTERRUPT_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_HID_MOUSE_INTERRUPT_IN_PACKET_SIZE, descriptorHead->endpoint.wMaxPacketSize); } else if (((descriptorHead->endpoint.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) == USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && (USB_HID_KEYBOARD_ENDPOINT_IN == (descriptorHead->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))) { descriptorHead->endpoint.bInterval = HS_HID_KEYBOARD_INTERRUPT_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_HID_KEYBOARD_INTERRUPT_IN_PACKET_SIZE, descriptorHead->endpoint.wMaxPacketSize); } else { } } else { if (((descriptorHead->endpoint.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) == USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && (USB_HID_MOUSE_ENDPOINT_IN == (descriptorHead->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))) { descriptorHead->endpoint.bInterval = FS_HID_MOUSE_INTERRUPT_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_HID_MOUSE_INTERRUPT_IN_PACKET_SIZE, descriptorHead->endpoint.wMaxPacketSize); } else if (((descriptorHead->endpoint.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) == USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && (USB_HID_KEYBOARD_ENDPOINT_IN == (descriptorHead->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))) { descriptorHead->endpoint.bInterval = FS_HID_KEYBOARD_INTERRUPT_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_HID_KEYBOARD_INTERRUPT_IN_PACKET_SIZE, descriptorHead->endpoint.wMaxPacketSize); } else { } } } descriptorHead = (usb_descriptor_union_t *)((uint8_t *)descriptorHead + descriptorHead->common.bLength); } if (USB_SPEED_HIGH == speed) { g_UsbDeviceHidMouseEndpoints[0].maxPacketSize = HS_HID_MOUSE_INTERRUPT_IN_PACKET_SIZE; } else { g_UsbDeviceHidMouseEndpoints[0].maxPacketSize = FS_HID_MOUSE_INTERRUPT_IN_PACKET_SIZE; } if (USB_SPEED_HIGH == speed) { g_UsbDeviceHidKeyboardEndpoints[0].maxPacketSize = HS_HID_KEYBOARD_INTERRUPT_IN_PACKET_SIZE; } else { g_UsbDeviceHidKeyboardEndpoints[0].maxPacketSize = FS_HID_KEYBOARD_INTERRUPT_IN_PACKET_SIZE; } return kStatus_USB_Success; }
/*! * @brief USB device set speed function. * * This function sets the speed of the USB devcie. * * @param handle The USB device handle. * @param speed Speed type. USB_SPEED_HIGH/USB_SPEED_FULL/USB_SPEED_LOW. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t usb_device_set_speed(usb_device_handle handle, uint8_t speed) { usb_hid_config_descriptor_t *ptr_hid = NULL; usb_msc_config_descriptor_t *ptr_msc = NULL; #if (USB_DEVICE_CONFIG_HID == 1) && (USB_DEVICE_CONFIG_MSC == 1) ptr_hid = (usb_hid_config_descriptor_t *)&g_config_descriptor[USB_HID_CONFIG_INDEX]; ptr_msc = (usb_msc_config_descriptor_t *)&g_config_descriptor[USB_MSC_CONFIG_INDEX]; #elif(USB_DEVICE_CONFIG_HID == 1) && (USB_DEVICE_CONFIG_MSC == 0) // HID only // ptr_msc = NULL; ptr_hid = (usb_hid_config_descriptor_t *)&g_config_descriptor[USB_HID_CONFIG_INDEX]; #elif(USB_DEVICE_CONFIG_HID == 0) && (USB_DEVICE_CONFIG_MSC == 1) // MSC only // ptr_hid = NULL; ptr_msc = (usb_msc_config_descriptor_t *)&g_config_descriptor[USB_MSC_CONFIG_INDEX]; #endif if (USB_SPEED_HIGH == speed) { if (ptr_hid != NULL) { // HID interface USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE, ptr_hid->endpoint_in.wMaxPacketSize); ptr_hid->endpoint_in.bInterval = HS_HID_GENERIC_INTERRUPT_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE, ptr_hid->endpoint_out.wMaxPacketSize); ptr_hid->endpoint_out.bInterval = HS_HID_GENERIC_INTERRUPT_OUT_INTERVAL; } if (ptr_msc != NULL) { // MSC interface USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_BULK_IN_PACKET_SIZE, ptr_msc->endpoint_in.wMaxPacketSize); USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_BULK_OUT_PACKET_SIZE, ptr_msc->endpoint_out.wMaxPacketSize); } } else { if (ptr_hid != NULL) { // HID interface USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE, ptr_hid->endpoint_in.wMaxPacketSize); ptr_hid->endpoint_in.bInterval = FS_HID_GENERIC_INTERRUPT_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE, ptr_hid->endpoint_out.wMaxPacketSize); ptr_hid->endpoint_out.bInterval = FS_HID_GENERIC_INTERRUPT_OUT_INTERVAL; } if (ptr_msc != NULL) { // MSC interface USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_BULK_IN_PACKET_SIZE, ptr_msc->endpoint_in.wMaxPacketSize); USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_BULK_OUT_PACKET_SIZE, ptr_msc->endpoint_out.wMaxPacketSize); } } for (uint32_t i = 0; i < USB_HID_GENERIC_ENDPOINT_COUNT; i++) { if (USB_SPEED_HIGH == speed) { if (g_hid_generic_endpoints[i].endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) { g_hid_generic_endpoints[i].maxPacketSize = HS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE; } else { g_hid_generic_endpoints[i].maxPacketSize = HS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE; } } else { if (g_hid_generic_endpoints[i].endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) { g_hid_generic_endpoints[i].maxPacketSize = FS_HID_GENERIC_INTERRUPT_IN_PACKET_SIZE; } else { g_hid_generic_endpoints[i].maxPacketSize = FS_HID_GENERIC_INTERRUPT_OUT_PACKET_SIZE; } } } for (uint32_t i = 0; i < USB_MSC_ENDPOINT_COUNT; i++) { if (USB_SPEED_HIGH == speed) { if ((USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT) == (g_msc_disk_endpoints[i].endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK)) { g_msc_disk_endpoints[i].maxPacketSize = HS_BULK_IN_PACKET_SIZE; } else { g_msc_disk_endpoints[i].maxPacketSize = HS_BULK_OUT_PACKET_SIZE; } } else { if ((USB_IN << USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_SHIFT) == (g_msc_disk_endpoints[i].endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK)) { g_msc_disk_endpoints[i].maxPacketSize = FS_BULK_IN_PACKET_SIZE; } else { g_msc_disk_endpoints[i].maxPacketSize = FS_BULK_OUT_PACKET_SIZE; } } } return kStatus_USB_Success; }
/*! * @brief USB device set speed function. * * This function sets the speed of the USB device. * * Due to the difference of HS and FS descriptors, the device descriptors and configurations need to be updated to match * current speed. * As the default, the device descriptors and configurations are configured by using FS parameters for both EHCI and * KHCI. * When the EHCI is enabled, the application needs to call this fucntion to update device by using current speed. * The updated information includes endpoint max packet size, endpoint interval, etc. * * @param handle The USB device handle. * @param speed Speed type. USB_SPEED_HIGH/USB_SPEED_FULL/USB_SPEED_LOW. * * @return A USB error code or kStatus_USB_Success. */ usb_status_t USB_DeviceSetSpeed(usb_device_handle handle, uint8_t speed) { usb_descriptor_union_t *ptr1; usb_descriptor_union_t *ptr2; ptr1 = (usb_descriptor_union_t *)(&g_UsbDeviceConfigurationDescriptor[0]); ptr2 = (usb_descriptor_union_t *)(&g_UsbDeviceConfigurationDescriptor[USB_DESCRIPTOR_LENGTH_CONFIGURATION_ALL - 1]); while (ptr1 < ptr2) { if (ptr1->common.bDescriptorType == USB_DESCRIPTOR_TYPE_ENDPOINT) { if (USB_SPEED_HIGH == speed) { if (((ptr1->endpoint.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && (USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT == (ptr1->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))) { ptr1->endpoint.bInterval = HS_CDC_VCOM_INTERRUPT_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE, ptr1->endpoint.wMaxPacketSize); } else if (((ptr1->endpoint.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && (USB_CDC_VCOM_BULK_IN_ENDPOINT == (ptr1->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))) { USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_CDC_VCOM_BULK_IN_PACKET_SIZE, ptr1->endpoint.wMaxPacketSize); } else if (((ptr1->endpoint.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) && (USB_CDC_VCOM_BULK_OUT_ENDPOINT == (ptr1->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))) { USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(HS_CDC_VCOM_BULK_OUT_PACKET_SIZE, ptr1->endpoint.wMaxPacketSize); } } else { if (((ptr1->endpoint.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && (USB_CDC_VCOM_INTERRUPT_IN_ENDPOINT == (ptr1->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))) { ptr1->endpoint.bInterval = FS_CDC_VCOM_INTERRUPT_IN_INTERVAL; USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE, ptr1->endpoint.wMaxPacketSize); } else if (((ptr1->endpoint.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_IN) && (USB_CDC_VCOM_BULK_IN_ENDPOINT == (ptr1->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))) { USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_CDC_VCOM_BULK_IN_PACKET_SIZE, ptr1->endpoint.wMaxPacketSize); } else if (((ptr1->endpoint.bEndpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) == USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_OUT) && (USB_CDC_VCOM_BULK_OUT_ENDPOINT == (ptr1->endpoint.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK))) { USB_SHORT_TO_LITTLE_ENDIAN_ADDRESS(FS_CDC_VCOM_BULK_OUT_PACKET_SIZE, ptr1->endpoint.wMaxPacketSize); } } } ptr1 = (usb_descriptor_union_t *)((uint8_t *)ptr1 + ptr1->common.bLength); } for (int i = 0; i < USB_CDC_VCOM_ENDPOINT_CIC_COUNT; i++) { if (USB_SPEED_HIGH == speed) { g_UsbDeviceCdcVcomCicEndpoints[i].maxPacketSize = HS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE; } else { g_UsbDeviceCdcVcomCicEndpoints[i].maxPacketSize = FS_CDC_VCOM_INTERRUPT_IN_PACKET_SIZE; } } for (int i = 0; i < USB_CDC_VCOM_ENDPOINT_DIC_COUNT; i++) { if (USB_SPEED_HIGH == speed) { if (g_UsbDeviceCdcVcomDicEndpoints[i].endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) { g_UsbDeviceCdcVcomDicEndpoints[i].maxPacketSize = HS_CDC_VCOM_BULK_IN_PACKET_SIZE; } else { g_UsbDeviceCdcVcomDicEndpoints[i].maxPacketSize = HS_CDC_VCOM_BULK_OUT_PACKET_SIZE; } } else { if (g_UsbDeviceCdcVcomDicEndpoints[i].endpointAddress & USB_DESCRIPTOR_ENDPOINT_ADDRESS_DIRECTION_MASK) { g_UsbDeviceCdcVcomDicEndpoints[i].maxPacketSize = FS_CDC_VCOM_BULK_IN_PACKET_SIZE; } else { g_UsbDeviceCdcVcomDicEndpoints[i].maxPacketSize = FS_CDC_VCOM_BULK_OUT_PACKET_SIZE; } } } return kStatus_USB_Success; }