Use background transfers for usb_keyboard
This commit is contained in:
parent
3ee4474e8d
commit
e959937cfd
4 changed files with 127 additions and 22 deletions
|
@ -195,29 +195,27 @@ grub_usb_control_msg (grub_usb_device_t dev,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static grub_usb_err_t
|
static grub_usb_transfer_t
|
||||||
grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
grub_usb_bulk_setup_readwrite (grub_usb_device_t dev,
|
||||||
int endpoint, grub_size_t size0, char *data_in,
|
int endpoint, grub_size_t size0, char *data_in,
|
||||||
grub_transfer_type_t type, int timeout,
|
grub_transfer_type_t type)
|
||||||
grub_size_t *actual)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
grub_usb_transfer_t transfer;
|
grub_usb_transfer_t transfer;
|
||||||
int datablocks;
|
int datablocks;
|
||||||
unsigned int max;
|
unsigned int max;
|
||||||
grub_usb_err_t err;
|
|
||||||
int toggle = dev->toggle[endpoint];
|
|
||||||
volatile char *data;
|
volatile char *data;
|
||||||
grub_uint32_t data_addr;
|
grub_uint32_t data_addr;
|
||||||
struct grub_pci_dma_chunk *data_chunk;
|
struct grub_pci_dma_chunk *data_chunk;
|
||||||
grub_size_t size = size0;
|
grub_size_t size = size0;
|
||||||
|
int toggle = dev->toggle[endpoint];
|
||||||
|
|
||||||
grub_dprintf ("usb", "bulk: size=0x%02x type=%d\n", size, type);
|
grub_dprintf ("usb", "bulk: size=0x%02x type=%d\n", size, type);
|
||||||
|
|
||||||
/* FIXME: avoid allocation any kind of buffer in a first place. */
|
/* FIXME: avoid allocation any kind of buffer in a first place. */
|
||||||
data_chunk = grub_memalign_dma32 (128, size);
|
data_chunk = grub_memalign_dma32 (128, size);
|
||||||
if (!data_chunk)
|
if (!data_chunk)
|
||||||
return GRUB_USB_ERR_INTERNAL;
|
return NULL;
|
||||||
data = grub_dma_get_virt (data_chunk);
|
data = grub_dma_get_virt (data_chunk);
|
||||||
data_addr = grub_dma_get_phys (data_chunk);
|
data_addr = grub_dma_get_phys (data_chunk);
|
||||||
if (type == GRUB_USB_TRANSFER_TYPE_OUT)
|
if (type == GRUB_USB_TRANSFER_TYPE_OUT)
|
||||||
|
@ -242,7 +240,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||||
if (! transfer)
|
if (! transfer)
|
||||||
{
|
{
|
||||||
grub_dma_free (data_chunk);
|
grub_dma_free (data_chunk);
|
||||||
return GRUB_USB_ERR_INTERNAL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
datablocks = ((size + max - 1) / max);
|
datablocks = ((size + max - 1) / max);
|
||||||
|
@ -251,9 +249,12 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||||
transfer->endpoint = endpoint & 15;
|
transfer->endpoint = endpoint & 15;
|
||||||
transfer->devaddr = dev->addr;
|
transfer->devaddr = dev->addr;
|
||||||
transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK;
|
transfer->type = GRUB_USB_TRANSACTION_TYPE_BULK;
|
||||||
|
transfer->dir = type;
|
||||||
transfer->max = max;
|
transfer->max = max;
|
||||||
transfer->dev = dev;
|
transfer->dev = dev;
|
||||||
transfer->last_trans = -1; /* Reset index of last processed transaction (TD) */
|
transfer->last_trans = -1; /* Reset index of last processed transaction (TD) */
|
||||||
|
transfer->data_chunk = data_chunk;
|
||||||
|
transfer->data = data_in;
|
||||||
|
|
||||||
/* Allocate an array of transfer data structures. */
|
/* Allocate an array of transfer data structures. */
|
||||||
transfer->transactions = grub_malloc (transfer->transcnt
|
transfer->transactions = grub_malloc (transfer->transcnt
|
||||||
|
@ -262,7 +263,7 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||||
{
|
{
|
||||||
grub_free (transfer);
|
grub_free (transfer);
|
||||||
grub_dma_free (data_chunk);
|
grub_dma_free (data_chunk);
|
||||||
return GRUB_USB_ERR_INTERNAL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set up all transfers. */
|
/* Set up all transfers. */
|
||||||
|
@ -280,24 +281,51 @@ grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||||
tr->preceding = i * max;
|
tr->preceding = i * max;
|
||||||
size -= tr->size;
|
size -= tr->size;
|
||||||
}
|
}
|
||||||
|
return transfer;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
grub_usb_bulk_finish_readwrite (grub_usb_transfer_t transfer)
|
||||||
|
{
|
||||||
|
grub_usb_device_t dev = transfer->dev;
|
||||||
|
int toggle = dev->toggle[transfer->endpoint];
|
||||||
|
|
||||||
err = grub_usb_execute_and_wait_transfer (dev, transfer, timeout, actual);
|
|
||||||
/* We must remember proper toggle value even if some transactions
|
/* We must remember proper toggle value even if some transactions
|
||||||
* were not processed - correct value should be inversion of last
|
* were not processed - correct value should be inversion of last
|
||||||
* processed transaction (TD). */
|
* processed transaction (TD). */
|
||||||
if (transfer->last_trans >= 0)
|
if (transfer->last_trans >= 0)
|
||||||
toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1;
|
toggle = transfer->transactions[transfer->last_trans].toggle ? 0 : 1;
|
||||||
else
|
else
|
||||||
toggle = dev->toggle[endpoint]; /* Nothing done, take original */
|
toggle = dev->toggle[transfer->endpoint]; /* Nothing done, take original */
|
||||||
grub_dprintf ("usb", "bulk: err=%d, toggle=%d\n", err, toggle);
|
grub_dprintf ("usb", "bulk: toggle=%d\n", toggle);
|
||||||
dev->toggle[endpoint] = toggle;
|
dev->toggle[transfer->endpoint] = toggle;
|
||||||
|
|
||||||
|
if (transfer->dir == GRUB_USB_TRANSFER_TYPE_IN)
|
||||||
|
grub_memcpy (transfer->data, (void *)
|
||||||
|
grub_dma_get_virt (transfer->data_chunk),
|
||||||
|
transfer->size + 1);
|
||||||
|
|
||||||
grub_free (transfer->transactions);
|
grub_free (transfer->transactions);
|
||||||
grub_free (transfer);
|
grub_free (transfer);
|
||||||
grub_dma_free (data_chunk);
|
grub_dma_free (transfer->data_chunk);
|
||||||
|
}
|
||||||
|
|
||||||
if (type == GRUB_USB_TRANSFER_TYPE_IN)
|
static grub_usb_err_t
|
||||||
grub_memcpy (data_in, (char *) data, size0);
|
grub_usb_bulk_readwrite (grub_usb_device_t dev,
|
||||||
|
int endpoint, grub_size_t size0, char *data_in,
|
||||||
|
grub_transfer_type_t type, int timeout,
|
||||||
|
grub_size_t *actual)
|
||||||
|
{
|
||||||
|
grub_usb_err_t err;
|
||||||
|
grub_usb_transfer_t transfer;
|
||||||
|
|
||||||
|
transfer = grub_usb_bulk_setup_readwrite (dev, endpoint, size0,
|
||||||
|
data_in, type);
|
||||||
|
if (!transfer)
|
||||||
|
return GRUB_USB_ERR_INTERNAL;
|
||||||
|
err = grub_usb_execute_and_wait_transfer (dev, transfer, timeout, actual);
|
||||||
|
|
||||||
|
grub_usb_bulk_finish_readwrite (transfer);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -329,6 +357,41 @@ grub_usb_bulk_read (grub_usb_device_t dev,
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_check_transfer (grub_usb_transfer_t transfer, grub_size_t *actual)
|
||||||
|
{
|
||||||
|
grub_usb_err_t err;
|
||||||
|
grub_usb_device_t dev = transfer->dev;
|
||||||
|
|
||||||
|
err = dev->controller.dev->check_transfer (&dev->controller, transfer,
|
||||||
|
actual);
|
||||||
|
if (err == GRUB_USB_ERR_WAIT)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
grub_usb_bulk_finish_readwrite (transfer);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_usb_transfer_t
|
||||||
|
grub_usb_bulk_read_background (grub_usb_device_t dev,
|
||||||
|
int endpoint, grub_size_t size, void *data)
|
||||||
|
{
|
||||||
|
grub_usb_err_t err;
|
||||||
|
grub_usb_transfer_t transfer;
|
||||||
|
|
||||||
|
transfer = grub_usb_bulk_setup_readwrite (dev, endpoint, size,
|
||||||
|
data, GRUB_USB_TRANSFER_TYPE_IN);
|
||||||
|
if (!transfer)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
err = dev->controller.dev->setup_transfer (&dev->controller, transfer);
|
||||||
|
if (err)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return transfer;
|
||||||
|
}
|
||||||
|
|
||||||
grub_usb_err_t
|
grub_usb_err_t
|
||||||
grub_usb_bulk_read_extended (grub_usb_device_t dev,
|
grub_usb_bulk_read_extended (grub_usb_device_t dev,
|
||||||
int endpoint, grub_size_t size, char *data,
|
int endpoint, grub_size_t size, char *data,
|
||||||
|
|
|
@ -274,5 +274,10 @@ grub_usb_err_t
|
||||||
grub_usb_bulk_read_extended (grub_usb_device_t dev,
|
grub_usb_bulk_read_extended (grub_usb_device_t dev,
|
||||||
int endpoint, grub_size_t size, char *data,
|
int endpoint, grub_size_t size, char *data,
|
||||||
int timeout, grub_size_t *actual);
|
int timeout, grub_size_t *actual);
|
||||||
|
grub_usb_transfer_t
|
||||||
|
grub_usb_bulk_read_background (grub_usb_device_t dev,
|
||||||
|
int endpoint, grub_size_t size, void *data);
|
||||||
|
grub_usb_err_t
|
||||||
|
grub_usb_check_transfer (grub_usb_transfer_t trans, grub_size_t *actual);
|
||||||
|
|
||||||
#endif /* GRUB_USB_H */
|
#endif /* GRUB_USB_H */
|
||||||
|
|
|
@ -56,6 +56,8 @@ struct grub_usb_transfer
|
||||||
|
|
||||||
grub_transaction_type_t type;
|
grub_transaction_type_t type;
|
||||||
|
|
||||||
|
grub_transfer_type_t dir;
|
||||||
|
|
||||||
struct grub_usb_device *dev;
|
struct grub_usb_device *dev;
|
||||||
|
|
||||||
struct grub_usb_transaction *transactions;
|
struct grub_usb_transaction *transactions;
|
||||||
|
@ -64,6 +66,10 @@ struct grub_usb_transfer
|
||||||
/* Index of last processed transaction in OHCI/UHCI driver. */
|
/* Index of last processed transaction in OHCI/UHCI driver. */
|
||||||
|
|
||||||
void *controller_data;
|
void *controller_data;
|
||||||
|
|
||||||
|
/* Used when finishing transfer to copy data back. */
|
||||||
|
struct grub_pci_dma_chunk *data_chunk;
|
||||||
|
void *data;
|
||||||
};
|
};
|
||||||
typedef struct grub_usb_transfer *grub_usb_transfer_t;
|
typedef struct grub_usb_transfer *grub_usb_transfer_t;
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,9 @@ struct grub_usb_keyboard_data
|
||||||
grub_uint8_t status;
|
grub_uint8_t status;
|
||||||
int key;
|
int key;
|
||||||
struct grub_usb_desc_endp *endp;
|
struct grub_usb_desc_endp *endp;
|
||||||
|
grub_usb_transfer_t transfer;
|
||||||
|
grub_uint8_t report[8];
|
||||||
|
int dead;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct grub_term_input grub_usb_keyboards[16];
|
static struct grub_term_input grub_usb_keyboards[16];
|
||||||
|
@ -214,8 +217,20 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
||||||
data->key = -1;
|
data->key = -1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
data->transfer = grub_usb_bulk_read_background (usbdev,
|
||||||
|
data->endp->endp_addr,
|
||||||
|
sizeof (data->report),
|
||||||
|
(char *) data->report);
|
||||||
|
if (!data->transfer)
|
||||||
|
{
|
||||||
|
grub_print_error ();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]);
|
grub_term_register_input_active ("usb_keyboard", &grub_usb_keyboards[curnum]);
|
||||||
|
|
||||||
|
data->dead = 0;
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,19 +239,35 @@ grub_usb_keyboard_attach (grub_usb_device_t usbdev, int configno, int interfno)
|
||||||
static int
|
static int
|
||||||
grub_usb_keyboard_checkkey (struct grub_term_input *term)
|
grub_usb_keyboard_checkkey (struct grub_term_input *term)
|
||||||
{
|
{
|
||||||
grub_uint8_t data[8];
|
|
||||||
grub_usb_err_t err;
|
grub_usb_err_t err;
|
||||||
struct grub_usb_keyboard_data *termdata = term->data;
|
struct grub_usb_keyboard_data *termdata = term->data;
|
||||||
|
grub_uint8_t data[sizeof (termdata->report)];
|
||||||
grub_size_t actual;
|
grub_size_t actual;
|
||||||
|
|
||||||
if (termdata->key != -1)
|
if (termdata->key != -1)
|
||||||
return termdata->key;
|
return termdata->key;
|
||||||
|
|
||||||
data[2] = 0;
|
if (termdata->dead)
|
||||||
|
return -1;
|
||||||
|
|
||||||
/* Poll interrupt pipe. */
|
/* Poll interrupt pipe. */
|
||||||
err = grub_usb_bulk_read_extended (termdata->usbdev,
|
err = grub_usb_check_transfer (termdata->transfer, &actual);
|
||||||
termdata->endp->endp_addr, sizeof (data),
|
|
||||||
(char *) data, 10, &actual);
|
if (err == GRUB_USB_ERR_WAIT)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
grub_memcpy (data, termdata->report, sizeof (data));
|
||||||
|
|
||||||
|
termdata->transfer = grub_usb_bulk_read_background (termdata->usbdev,
|
||||||
|
termdata->endp->endp_addr,
|
||||||
|
sizeof (termdata->report),
|
||||||
|
(char *) termdata->report);
|
||||||
|
if (!termdata->transfer)
|
||||||
|
{
|
||||||
|
grub_printf ("%s failed. Stopped\n", term->name);
|
||||||
|
termdata->dead = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (err || actual < 1)
|
if (err || actual < 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue