mirror of
https://github.com/u-boot/u-boot.git
synced 2024-12-04 10:03:41 +08:00
This commit is contained in:
commit
b03b49046a
70
common/usb.c
70
common/usb.c
@ -28,6 +28,7 @@
|
|||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <command.h>
|
#include <command.h>
|
||||||
#include <dm.h>
|
#include <dm.h>
|
||||||
|
#include <dm/device_compat.h>
|
||||||
#include <log.h>
|
#include <log.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <memalign.h>
|
#include <memalign.h>
|
||||||
@ -1084,6 +1085,54 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int usb_device_is_ignored(u16 id_vendor, u16 id_product)
|
||||||
|
{
|
||||||
|
ulong vid, pid;
|
||||||
|
char *end;
|
||||||
|
const char *cur = NULL;
|
||||||
|
|
||||||
|
/* ignore list depends on env support */
|
||||||
|
if (!CONFIG_IS_ENABLED(ENV_SUPPORT))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cur = env_get("usb_ignorelist");
|
||||||
|
|
||||||
|
/* parse "usb_ignorelist" strictly */
|
||||||
|
while (cur && cur[0] != '\0') {
|
||||||
|
vid = simple_strtoul(cur, &end, 0);
|
||||||
|
/*
|
||||||
|
* If strtoul did not parse a single digit or the next char is
|
||||||
|
* not ':' the ignore list is malformed.
|
||||||
|
*/
|
||||||
|
if (cur == end || end[0] != ':')
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
cur = end + 1;
|
||||||
|
pid = simple_strtoul(cur, &end, 0);
|
||||||
|
/* Consider '*' as wildcard for the product ID */
|
||||||
|
if (cur == end && end[0] == '*') {
|
||||||
|
pid = U16_MAX + 1;
|
||||||
|
end++;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* The ignore list is malformed if no product ID / wildcard was
|
||||||
|
* parsed or entries are not separated by ',' or terminated with
|
||||||
|
* '\0'.
|
||||||
|
*/
|
||||||
|
if (cur == end || (end[0] != ',' && end[0] != '\0'))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (id_vendor == vid && (pid > U16_MAX || id_product == pid))
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (end[0] == '\0')
|
||||||
|
break;
|
||||||
|
cur = end + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int usb_select_config(struct usb_device *dev)
|
int usb_select_config(struct usb_device *dev)
|
||||||
{
|
{
|
||||||
unsigned char *tmpbuf = NULL;
|
unsigned char *tmpbuf = NULL;
|
||||||
@ -1099,6 +1148,27 @@ int usb_select_config(struct usb_device *dev)
|
|||||||
le16_to_cpus(&dev->descriptor.idProduct);
|
le16_to_cpus(&dev->descriptor.idProduct);
|
||||||
le16_to_cpus(&dev->descriptor.bcdDevice);
|
le16_to_cpus(&dev->descriptor.bcdDevice);
|
||||||
|
|
||||||
|
/* ignore devices from usb_ignorelist */
|
||||||
|
err = usb_device_is_ignored(dev->descriptor.idVendor,
|
||||||
|
dev->descriptor.idProduct);
|
||||||
|
if (err == -ENODEV) {
|
||||||
|
debug("Ignoring USB device 0x%x:0x%x\n",
|
||||||
|
dev->descriptor.idVendor, dev->descriptor.idProduct);
|
||||||
|
return err;
|
||||||
|
} else if (err == -EINVAL) {
|
||||||
|
/*
|
||||||
|
* Continue on "usb_ignorelist" parsing errors. The list is
|
||||||
|
* parsed for each device returning the error would result in
|
||||||
|
* ignoring all USB devices.
|
||||||
|
* Since the parsing error is independent of the probed device
|
||||||
|
* report errors with printf instead of dev_err.
|
||||||
|
*/
|
||||||
|
printf("usb_ignorelist parse error in \"%s\"\n",
|
||||||
|
env_get("usb_ignorelist"));
|
||||||
|
} else if (err < 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kingston DT Ultimate 32GB USB 3.0 seems to be extremely sensitive
|
* Kingston DT Ultimate 32GB USB 3.0 seems to be extremely sensitive
|
||||||
* about this first Get Descriptor request. If there are any other
|
* about this first Get Descriptor request. If there are any other
|
||||||
|
@ -23,6 +23,18 @@
|
|||||||
|
|
||||||
#include <usb.h>
|
#include <usb.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* USB vendor and product IDs used for quirks.
|
||||||
|
*/
|
||||||
|
#define USB_VENDOR_ID_APPLE 0x05ac
|
||||||
|
#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021 0x029c
|
||||||
|
#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021 0x029a
|
||||||
|
#define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021 0x029f
|
||||||
|
|
||||||
|
#define USB_VENDOR_ID_KEYCHRON 0x3434
|
||||||
|
|
||||||
|
#define USB_HID_QUIRK_POLL_NO_REPORT_IDLE BIT(0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If overwrite_console returns 1, the stdin, stderr and stdout
|
* If overwrite_console returns 1, the stdin, stderr and stdout
|
||||||
* are switched to the serial port, else the settings in the
|
* are switched to the serial port, else the settings in the
|
||||||
@ -106,6 +118,8 @@ struct usb_kbd_pdata {
|
|||||||
unsigned long last_report;
|
unsigned long last_report;
|
||||||
struct int_queue *intq;
|
struct int_queue *intq;
|
||||||
|
|
||||||
|
uint32_t ifnum;
|
||||||
|
|
||||||
uint32_t repeat_delay;
|
uint32_t repeat_delay;
|
||||||
|
|
||||||
uint32_t usb_in_pointer;
|
uint32_t usb_in_pointer;
|
||||||
@ -150,8 +164,8 @@ static void usb_kbd_put_queue(struct usb_kbd_pdata *data, u8 c)
|
|||||||
*/
|
*/
|
||||||
static void usb_kbd_setled(struct usb_device *dev)
|
static void usb_kbd_setled(struct usb_device *dev)
|
||||||
{
|
{
|
||||||
struct usb_interface *iface = &dev->config.if_desc[0];
|
|
||||||
struct usb_kbd_pdata *data = dev->privptr;
|
struct usb_kbd_pdata *data = dev->privptr;
|
||||||
|
struct usb_interface *iface = &dev->config.if_desc[data->ifnum];
|
||||||
ALLOC_ALIGN_BUFFER(uint32_t, leds, 1, USB_DMA_MINALIGN);
|
ALLOC_ALIGN_BUFFER(uint32_t, leds, 1, USB_DMA_MINALIGN);
|
||||||
|
|
||||||
*leds = data->flags & USB_KBD_LEDMASK;
|
*leds = data->flags & USB_KBD_LEDMASK;
|
||||||
@ -365,7 +379,7 @@ static inline void usb_kbd_poll_for_event(struct usb_device *dev)
|
|||||||
#if defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP)
|
#if defined(CONFIG_SYS_USB_EVENT_POLL_VIA_CONTROL_EP)
|
||||||
struct usb_interface *iface;
|
struct usb_interface *iface;
|
||||||
struct usb_kbd_pdata *data = dev->privptr;
|
struct usb_kbd_pdata *data = dev->privptr;
|
||||||
iface = &dev->config.if_desc[0];
|
iface = &dev->config.if_desc[data->ifnum];
|
||||||
usb_get_report(dev, iface->desc.bInterfaceNumber,
|
usb_get_report(dev, iface->desc.bInterfaceNumber,
|
||||||
1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE);
|
1, 0, data->new, USB_KBD_BOOT_REPORT_SIZE);
|
||||||
if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) {
|
if (memcmp(data->old, data->new, USB_KBD_BOOT_REPORT_SIZE)) {
|
||||||
@ -464,6 +478,7 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum)
|
|||||||
struct usb_interface *iface;
|
struct usb_interface *iface;
|
||||||
struct usb_endpoint_descriptor *ep;
|
struct usb_endpoint_descriptor *ep;
|
||||||
struct usb_kbd_pdata *data;
|
struct usb_kbd_pdata *data;
|
||||||
|
unsigned int quirks = 0;
|
||||||
int epNum;
|
int epNum;
|
||||||
|
|
||||||
if (dev->descriptor.bNumConfigurations != 1)
|
if (dev->descriptor.bNumConfigurations != 1)
|
||||||
@ -496,6 +511,15 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum)
|
|||||||
|
|
||||||
debug("USB KBD: found interrupt EP: 0x%x\n", ep->bEndpointAddress);
|
debug("USB KBD: found interrupt EP: 0x%x\n", ep->bEndpointAddress);
|
||||||
|
|
||||||
|
switch (dev->descriptor.idVendor) {
|
||||||
|
case USB_VENDOR_ID_APPLE:
|
||||||
|
case USB_VENDOR_ID_KEYCHRON:
|
||||||
|
quirks |= USB_HID_QUIRK_POLL_NO_REPORT_IDLE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
data = malloc(sizeof(struct usb_kbd_pdata));
|
data = malloc(sizeof(struct usb_kbd_pdata));
|
||||||
if (!data) {
|
if (!data) {
|
||||||
printf("USB KBD: Error allocating private data\n");
|
printf("USB KBD: Error allocating private data\n");
|
||||||
@ -509,6 +533,8 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum)
|
|||||||
data->new = memalign(USB_DMA_MINALIGN,
|
data->new = memalign(USB_DMA_MINALIGN,
|
||||||
roundup(USB_KBD_BOOT_REPORT_SIZE, USB_DMA_MINALIGN));
|
roundup(USB_KBD_BOOT_REPORT_SIZE, USB_DMA_MINALIGN));
|
||||||
|
|
||||||
|
data->ifnum = ifnum;
|
||||||
|
|
||||||
/* Insert private data into USB device structure */
|
/* Insert private data into USB device structure */
|
||||||
dev->privptr = data;
|
dev->privptr = data;
|
||||||
|
|
||||||
@ -534,6 +560,14 @@ static int usb_kbd_probe_dev(struct usb_device *dev, unsigned int ifnum)
|
|||||||
usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0);
|
usb_set_idle(dev, iface->desc.bInterfaceNumber, 0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Apple and Keychron keyboards do not report the device state. Reports
|
||||||
|
* are only returned during key presses.
|
||||||
|
*/
|
||||||
|
if (quirks & USB_HID_QUIRK_POLL_NO_REPORT_IDLE) {
|
||||||
|
debug("USB KBD: quirk: skip testing device state\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
debug("USB KBD: enable interrupt pipe...\n");
|
debug("USB KBD: enable interrupt pipe...\n");
|
||||||
#ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
|
#ifdef CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE
|
||||||
data->intq = create_int_queue(dev, data->intpipe, 1,
|
data->intq = create_int_queue(dev, data->intpipe, 1,
|
||||||
@ -561,10 +595,17 @@ static int probe_usb_keyboard(struct usb_device *dev)
|
|||||||
{
|
{
|
||||||
char *stdinname;
|
char *stdinname;
|
||||||
struct stdio_dev usb_kbd_dev;
|
struct stdio_dev usb_kbd_dev;
|
||||||
|
unsigned int ifnum;
|
||||||
|
unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES,
|
||||||
|
(unsigned int)dev->config.no_of_if);
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* Try probing the keyboard */
|
/* Try probing the keyboard */
|
||||||
if (usb_kbd_probe_dev(dev, 0) != 1)
|
for (ifnum = 0; ifnum < max_ifnum; ifnum++) {
|
||||||
|
if (usb_kbd_probe_dev(dev, ifnum) == 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (ifnum >= max_ifnum)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
/* Register the keyboard */
|
/* Register the keyboard */
|
||||||
@ -731,6 +772,18 @@ static const struct usb_device_id kbd_id_table[] = {
|
|||||||
.bInterfaceSubClass = USB_SUB_HID_BOOT,
|
.bInterfaceSubClass = USB_SUB_HID_BOOT,
|
||||||
.bInterfaceProtocol = USB_PROT_HID_KEYBOARD,
|
.bInterfaceProtocol = USB_PROT_HID_KEYBOARD,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||||
|
USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||||
|
USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
USB_DEVICE(USB_VENDOR_ID_APPLE,
|
||||||
|
USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021),
|
||||||
|
},
|
||||||
{ } /* Terminating entry */
|
{ } /* Terminating entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -366,6 +366,19 @@ tftpwindowsize
|
|||||||
This means the count of blocks we can receive before
|
This means the count of blocks we can receive before
|
||||||
sending ack to server.
|
sending ack to server.
|
||||||
|
|
||||||
|
usb_ignorelist
|
||||||
|
Ignore USB devices to prevent binding them to an USB device driver. This can
|
||||||
|
be used to ignore devices are for some reason undesirable or causes crashes
|
||||||
|
u-boot's USB stack.
|
||||||
|
An example for undesired behavior is the keyboard emulation of security keys
|
||||||
|
like Yubikeys. U-boot currently supports only a single USB keyboard device
|
||||||
|
so try to probe an useful keyboard device. The default environment blocks
|
||||||
|
Yubico devices as common devices emulating keyboards.
|
||||||
|
Devices are matched by idVendor and idProduct. The variable contains a comma
|
||||||
|
separated list of idVendor:idProduct pairs as hexadecimal numbers joined
|
||||||
|
by a colon. '*' functions as a wildcard for idProduct to block all devices
|
||||||
|
with the specified idVendor.
|
||||||
|
|
||||||
vlan
|
vlan
|
||||||
When set to a value < 4095 the traffic over
|
When set to a value < 4095 the traffic over
|
||||||
Ethernet is encapsulated/received over 802.1q
|
Ethernet is encapsulated/received over 802.1q
|
||||||
|
@ -685,6 +685,9 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe,
|
|||||||
reset_ep(udev, ep_index);
|
reset_ep(udev, ep_index);
|
||||||
|
|
||||||
ring = virt_dev->eps[ep_index].ring;
|
ring = virt_dev->eps[ep_index].ring;
|
||||||
|
if (!ring)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* How much data is (potentially) left before the 64KB boundary?
|
* How much data is (potentially) left before the 64KB boundary?
|
||||||
* XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec)
|
* XHCI Spec puts restriction( TABLE 49 and 6.4.1 section of XHCI Spec)
|
||||||
@ -871,6 +874,8 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
|
|||||||
ep_index = usb_pipe_ep_index(pipe);
|
ep_index = usb_pipe_ep_index(pipe);
|
||||||
|
|
||||||
ep_ring = virt_dev->eps[ep_index].ring;
|
ep_ring = virt_dev->eps[ep_index].ring;
|
||||||
|
if (!ep_ring)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check to see if the max packet size for the default control
|
* Check to see if the max packet size for the default control
|
||||||
|
@ -475,67 +475,34 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the endpoint, programming the device contexts.
|
* Fill endpoint contexts for interface descriptor ifdesc.
|
||||||
*
|
*
|
||||||
* @param udev pointer to the USB device structure
|
* @param udev pointer to the USB device structure
|
||||||
* Return: returns the status of the xhci_configure_endpoints
|
* @param ctrl pointer to the xhci pravte device structure
|
||||||
|
* @param virt_dev pointer to the xhci virtual device structure
|
||||||
|
* @param ifdesc pointer to the USB interface config descriptor
|
||||||
|
* Return: returns the status of xhci_init_ep_contexts_if
|
||||||
*/
|
*/
|
||||||
static int xhci_set_configuration(struct usb_device *udev)
|
static int xhci_init_ep_contexts_if(struct usb_device *udev,
|
||||||
|
struct xhci_ctrl *ctrl,
|
||||||
|
struct xhci_virt_device *virt_dev,
|
||||||
|
struct usb_interface *ifdesc
|
||||||
|
)
|
||||||
{
|
{
|
||||||
struct xhci_container_ctx *in_ctx;
|
|
||||||
struct xhci_container_ctx *out_ctx;
|
|
||||||
struct xhci_input_control_ctx *ctrl_ctx;
|
|
||||||
struct xhci_slot_ctx *slot_ctx;
|
|
||||||
struct xhci_ep_ctx *ep_ctx[MAX_EP_CTX_NUM];
|
struct xhci_ep_ctx *ep_ctx[MAX_EP_CTX_NUM];
|
||||||
int cur_ep;
|
int cur_ep;
|
||||||
int max_ep_flag = 0;
|
|
||||||
int ep_index;
|
int ep_index;
|
||||||
unsigned int dir;
|
unsigned int dir;
|
||||||
unsigned int ep_type;
|
unsigned int ep_type;
|
||||||
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
|
|
||||||
int num_of_ep;
|
|
||||||
int ep_flag = 0;
|
|
||||||
u64 trb_64 = 0;
|
u64 trb_64 = 0;
|
||||||
int slot_id = udev->slot_id;
|
|
||||||
struct xhci_virt_device *virt_dev = ctrl->devs[slot_id];
|
|
||||||
struct usb_interface *ifdesc;
|
|
||||||
u32 max_esit_payload;
|
u32 max_esit_payload;
|
||||||
unsigned int interval;
|
unsigned int interval;
|
||||||
unsigned int mult;
|
unsigned int mult;
|
||||||
unsigned int max_burst;
|
unsigned int max_burst;
|
||||||
unsigned int avg_trb_len;
|
unsigned int avg_trb_len;
|
||||||
unsigned int err_count = 0;
|
unsigned int err_count = 0;
|
||||||
|
int num_of_ep = ifdesc->no_of_ep;
|
||||||
|
|
||||||
out_ctx = virt_dev->out_ctx;
|
|
||||||
in_ctx = virt_dev->in_ctx;
|
|
||||||
|
|
||||||
num_of_ep = udev->config.if_desc[0].no_of_ep;
|
|
||||||
ifdesc = &udev->config.if_desc[0];
|
|
||||||
|
|
||||||
ctrl_ctx = xhci_get_input_control_ctx(in_ctx);
|
|
||||||
/* Initialize the input context control */
|
|
||||||
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG);
|
|
||||||
ctrl_ctx->drop_flags = 0;
|
|
||||||
|
|
||||||
/* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */
|
|
||||||
for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) {
|
|
||||||
ep_flag = xhci_get_ep_index(&ifdesc->ep_desc[cur_ep]);
|
|
||||||
ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1));
|
|
||||||
if (max_ep_flag < ep_flag)
|
|
||||||
max_ep_flag = ep_flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size);
|
|
||||||
|
|
||||||
/* slot context */
|
|
||||||
xhci_slot_copy(ctrl, in_ctx, out_ctx);
|
|
||||||
slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx);
|
|
||||||
slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK));
|
|
||||||
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0);
|
|
||||||
|
|
||||||
xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0);
|
|
||||||
|
|
||||||
/* filling up ep contexts */
|
|
||||||
for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) {
|
for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) {
|
||||||
struct usb_endpoint_descriptor *endpt_desc = NULL;
|
struct usb_endpoint_descriptor *endpt_desc = NULL;
|
||||||
struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc = NULL;
|
struct usb_ss_ep_comp_descriptor *ss_ep_comp_desc = NULL;
|
||||||
@ -561,7 +528,8 @@ static int xhci_set_configuration(struct usb_device *udev)
|
|||||||
avg_trb_len = max_esit_payload;
|
avg_trb_len = max_esit_payload;
|
||||||
|
|
||||||
ep_index = xhci_get_ep_index(endpt_desc);
|
ep_index = xhci_get_ep_index(endpt_desc);
|
||||||
ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, in_ctx, ep_index);
|
ep_ctx[ep_index] = xhci_get_ep_ctx(ctrl, virt_dev->in_ctx,
|
||||||
|
ep_index);
|
||||||
|
|
||||||
/* Allocate the ep rings */
|
/* Allocate the ep rings */
|
||||||
virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true);
|
virt_dev->eps[ep_index].ring = xhci_ring_alloc(ctrl, 1, true);
|
||||||
@ -614,6 +582,72 @@ static int xhci_set_configuration(struct usb_device *udev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the endpoint, programming the device contexts.
|
||||||
|
*
|
||||||
|
* @param udev pointer to the USB device structure
|
||||||
|
* Return: returns the status of the xhci_configure_endpoints
|
||||||
|
*/
|
||||||
|
static int xhci_set_configuration(struct usb_device *udev)
|
||||||
|
{
|
||||||
|
struct xhci_container_ctx *out_ctx;
|
||||||
|
struct xhci_container_ctx *in_ctx;
|
||||||
|
struct xhci_input_control_ctx *ctrl_ctx;
|
||||||
|
struct xhci_slot_ctx *slot_ctx;
|
||||||
|
int err;
|
||||||
|
int cur_ep;
|
||||||
|
int max_ep_flag = 0;
|
||||||
|
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
|
||||||
|
int num_of_ep;
|
||||||
|
int ep_flag = 0;
|
||||||
|
int slot_id = udev->slot_id;
|
||||||
|
struct xhci_virt_device *virt_dev = ctrl->devs[slot_id];
|
||||||
|
struct usb_interface *ifdesc;
|
||||||
|
unsigned int ifnum;
|
||||||
|
unsigned int max_ifnum = min((unsigned int)USB_MAX_ACTIVE_INTERFACES,
|
||||||
|
(unsigned int)udev->config.no_of_if);
|
||||||
|
|
||||||
|
out_ctx = virt_dev->out_ctx;
|
||||||
|
in_ctx = virt_dev->in_ctx;
|
||||||
|
|
||||||
|
ctrl_ctx = xhci_get_input_control_ctx(in_ctx);
|
||||||
|
/* Initialize the input context control */
|
||||||
|
ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG);
|
||||||
|
ctrl_ctx->drop_flags = 0;
|
||||||
|
|
||||||
|
for (ifnum = 0; ifnum < max_ifnum; ifnum++) {
|
||||||
|
ifdesc = &udev->config.if_desc[ifnum];
|
||||||
|
num_of_ep = ifdesc->no_of_ep;
|
||||||
|
/* EP_FLAG gives values 1 & 4 for EP1OUT and EP2IN */
|
||||||
|
for (cur_ep = 0; cur_ep < num_of_ep; cur_ep++) {
|
||||||
|
ep_flag = xhci_get_ep_index(&ifdesc->ep_desc[cur_ep]);
|
||||||
|
ctrl_ctx->add_flags |= cpu_to_le32(1 << (ep_flag + 1));
|
||||||
|
if (max_ep_flag < ep_flag)
|
||||||
|
max_ep_flag = ep_flag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xhci_inval_cache((uintptr_t)out_ctx->bytes, out_ctx->size);
|
||||||
|
|
||||||
|
/* slot context */
|
||||||
|
xhci_slot_copy(ctrl, in_ctx, out_ctx);
|
||||||
|
slot_ctx = xhci_get_slot_ctx(ctrl, in_ctx);
|
||||||
|
slot_ctx->dev_info &= ~(cpu_to_le32(LAST_CTX_MASK));
|
||||||
|
slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(max_ep_flag + 1) | 0);
|
||||||
|
|
||||||
|
xhci_endpoint_copy(ctrl, in_ctx, out_ctx, 0);
|
||||||
|
|
||||||
|
/* filling up ep contexts */
|
||||||
|
for (ifnum = 0; ifnum < max_ifnum; ifnum++) {
|
||||||
|
ifdesc = &udev->config.if_desc[ifnum];
|
||||||
|
err = xhci_init_ep_contexts_if(udev, ctrl, virt_dev, ifdesc);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
return xhci_configure_endpoints(udev, false);
|
return xhci_configure_endpoints(udev, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +99,17 @@ const char default_environment[] = {
|
|||||||
#ifdef CONFIG_SYS_SOC
|
#ifdef CONFIG_SYS_SOC
|
||||||
"soc=" CONFIG_SYS_SOC "\0"
|
"soc=" CONFIG_SYS_SOC "\0"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_USB_HOST
|
||||||
|
"usb_ignorelist="
|
||||||
|
#ifdef CONFIG_USB_KEYBOARD
|
||||||
|
/* Ignore Yubico devices. Currently only a single USB keyboard device is
|
||||||
|
* supported and the emulated HID keyboard Yubikeys present is useless
|
||||||
|
* as keyboard.
|
||||||
|
*/
|
||||||
|
"0x1050:*,"
|
||||||
|
#endif
|
||||||
|
"\0"
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_ENV_IMPORT_FDT
|
#ifdef CONFIG_ENV_IMPORT_FDT
|
||||||
"env_fdt_path=" CONFIG_ENV_FDT_PATH "\0"
|
"env_fdt_path=" CONFIG_ENV_FDT_PATH "\0"
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,6 +49,12 @@ extern bool usb_started; /* flag for the started/stopped USB status */
|
|||||||
*/
|
*/
|
||||||
#define USB_TIMEOUT_MS(pipe) (usb_pipebulk(pipe) ? 5000 : 1000)
|
#define USB_TIMEOUT_MS(pipe) (usb_pipebulk(pipe) ? 5000 : 1000)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The xhcd hcd driver prepares only a limited number interfaces / endpoints.
|
||||||
|
* Define this limit so that drivers do not exceed it.
|
||||||
|
*/
|
||||||
|
#define USB_MAX_ACTIVE_INTERFACES 2
|
||||||
|
|
||||||
/* device request (setup) */
|
/* device request (setup) */
|
||||||
struct devrequest {
|
struct devrequest {
|
||||||
__u8 requesttype;
|
__u8 requesttype;
|
||||||
|
Loading…
Reference in New Issue
Block a user