/* usbtrans.c - USB Transfers and Transactions. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
*
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/usbtrans.h>
static grub_usb_err_t
{
if (err)
return err;
/* endtime moved behind setup transfer to prevent false timeouts
* while debugging... */
while (1)
{
actual);
if (!err)
return GRUB_USB_ERR_NONE;
if (err != GRUB_USB_ERR_WAIT)
return err;
if (grub_get_time_ms () > endtime)
{
transfer);
if (err)
return err;
return GRUB_USB_ERR_TIMEOUT;
}
grub_cpu_idle ();
}
}
{
int i;
int datablocks;
unsigned int max;
volatile char *data;
/* FIXME: avoid allocation any kind of buffer in a first place. */
if (!data_chunk)
return GRUB_USB_ERR_INTERNAL;
grub_dprintf ("usb",
"control: reqtype=0x%02x req=0x%02x val=0x%02x idx=0x%02x size=%lu\n",
/* Create a transfer. */
if (! transfer)
{
return GRUB_USB_ERR_INTERNAL;
}
if (! setupdata_chunk)
{
return GRUB_USB_ERR_INTERNAL;
}
/* Determine the maximum packet size. */
else
max = 64;
/* XXX: Discriminate between different types of control
messages. */
/* Allocate an array of transfer data structures. */
* sizeof (struct grub_usb_transfer));
if (! transfer->transactions)
{
return GRUB_USB_ERR_INTERNAL;
}
/* Build a Setup packet. XXX: Endianness. */
/* Now the data... XXX: Is this the right way to transfer control
transfers? */
for (i = 0; i < datablocks; i++)
{
/* Use the right most bit as the data toggle. Simple and
effective. */
if (reqtype & 128)
else
}
/* End with an empty OUT transaction. */
else
return err;
}
static grub_usb_transfer_t
{
int i;
int datablocks;
unsigned int max;
volatile char *data;
type);
/* FIXME: avoid allocation any kind of buffer in a first place. */
if (!data_chunk)
return NULL;
if (type == GRUB_USB_TRANSFER_TYPE_OUT)
/* Use the maximum packet size given in the endpoint descriptor. */
if (dev->initialized)
{
if (endpdesc)
else
max = 64;
}
else
max = 64;
/* Create a transfer. */
if (! transfer)
{
return NULL;
}
/* Allocate an array of transfer data structures. */
* sizeof (struct grub_usb_transfer));
if (! transfer->transactions)
{
return NULL;
}
/* Set up all transfers. */
for (i = 0; i < datablocks; i++)
{
/* XXX: Use the right most bit as the data toggle. Simple and
effective. */
}
return transfer;
}
static void
{
/* We must remember proper toggle value even if some transactions
* were not processed - correct value should be inversion of last
* processed transaction (TD). */
if (transfer->last_trans >= 0)
else
}
static grub_usb_err_t
{
if (!transfer)
return GRUB_USB_ERR_INTERNAL;
return err;
}
{
return err;
}
{
return err;
}
{
actual);
if (err == GRUB_USB_ERR_WAIT)
return err;
return err;
}
{
if (!transfer)
return NULL;
if (err)
return NULL;
return transfer;
}
void
{
}
{
}