📄 usbhost.c
字号:
while (i < length) {
switch (bf[i+1]) {
case CONFIGURATION_TYPE:
++Config_no;
if (Config_no > DeviceDesc.bNumConfigurations) {
VPRINT("More than %d many configurations\n",
DeviceDesc.bNumConfigurations);
return FALSE;
}
BCOPY(&bf[i], (Uint8 *)&ConfigDesc, sizeof(CONFIG_DESC));
#if USBH_VERBOSE
PSPRINTF("\nConfiguration no.: %d\n",
ConfigDesc.bConfigurationValue);
PSPRINTF(" Total length of configuration: %d\n",
ConfigDesc.wTotalLength_high*256 +
ConfigDesc.wTotalLength_low);
PSPRINTF(" No. of Interfaces: %d\n", ConfigDesc.bNumInterfaces);
if (ConfigDesc.iConfiguration) {
PSPRINTF("Configuration name: ");
USB_PrintString(ConfigDesc.iConfiguration, lang_id);
}
PSPRINTF(" Configuration attributes: %02x\n Max Power: %d mA.\n",
ConfigDesc.bmAttributes, ConfigDesc.bMaxPower);
#endif
break;
case INTERFACE_TYPE:
if (bf[i] != sizeof(INTERFACE_DESC)) {
VPRINT("Bad Interface desc, size %d\n", bf[i]);
return FALSE;
}
BCOPY(&bf[i], (Uint8 *)&InterfaceDesc, sizeof(INTERFACE_DESC));
gotIface = TRUE;
EndPointCount = 0;
#if USBH_VERBOSE
PSPRINTF("\n Interface Descriptor %02x Alt: %02x:\n",
InterfaceDesc.bInterfaceNumber,
InterfaceDesc.bAlternateSetting);
if (InterfaceDesc.iInterface) {
PSPRINTF(" Interface[%d]: ", InterfaceDesc.iInterface);
USB_PrintString(InterfaceDesc.iInterface, lang_id);
}
PSPRINTF(" %d endpoints\n Class %02x ",
InterfaceDesc.bNumEndpoints,
InterfaceDesc.bInterfaceClass);
switch (InterfaceDesc.bInterfaceClass) {
case 3:
PSPRINTF("HID Class\n");
break;
case 6:
PSPRINTF("Still Image Capture Device Class\n");
break;
case 7:
PSPRINTF("Printer Class\n");
break;
case 8:
PSPRINTF("Mass Storage Class\n");
break;
case 0xff:
PSPRINTF("Vendor specific\n");
break;
default:
PSPRINTF("class unknown\n");
}
PSPRINTF(" Subclass %02x\n Protocol %02x\n",
InterfaceDesc.bInterfaceSubClass,
InterfaceDesc.bInterfaceProtocol);
#endif
if (InterfaceDesc.bInterfaceNumber >= ConfigDesc.bNumInterfaces) {
VPRINT("ERROR: InterfaceNumber %d > NumInterfaces %d\n",
InterfaceDesc.bInterfaceNumber,
ConfigDesc.bNumInterfaces);
gotIface = FALSE;
}
else if (MassStorage.needClass &&
InterfaceDesc.bInterfaceClass == 8 &&
InterfaceDesc.bInterfaceSubClass == 6 &&
InterfaceDesc.bInterfaceProtocol == 0x50)
{
MassStorage.Config = Config_no;
MassStorage.iface = InterfaceDesc.bInterfaceNumber;
MassStorage.ifaceAlt = InterfaceDesc.bAlternateSetting;
MassStorage.ep_in = 0;
MassStorage.ep_out = 0;
MassStorage.ep_intr = 0;
}
else if (StillImage.needClass &&
InterfaceDesc.bInterfaceClass == 6 &&
InterfaceDesc.bInterfaceSubClass == 1 &&
InterfaceDesc.bInterfaceProtocol == 1)
{
StillImage.Config = Config_no;
StillImage.iface = InterfaceDesc.bInterfaceNumber;
StillImage.ifaceAlt = InterfaceDesc.bAlternateSetting;
StillImage.ep_in = 0;
StillImage.ep_out = 0;
StillImage.ep_intr = 0;
}
break;
case ENDPOINT_TYPE:
if (bf[i] != sizeof(ENDPOINT_DESC)) {
VPRINT("Bad Endpoint desc, size %d\n", bf[i]);
return FALSE;
}
BCOPY(&bf[i], (Uint8 *)&EndpointDesc, sizeof(ENDPOINT_DESC));
++EndPointCount;
#if USBH_VERBOSE
PSPRINTF("\n Endpoint Descriptor[%d]%s: EP %d %s\n",
EndPointCount, (gotIface ? "" : " (ignored)"),
(EndpointDesc.bEPAddress & 15),
((EndpointDesc.bEPAddress & 0x80) ? "IN":"OUT"));
if ((EndpointDesc.bmAttributes & 3) == 0)
PSPRINTF(" CNTRL");
else if ((EndpointDesc.bmAttributes & 3) == 1)
PSPRINTF(" ISO ");
else if ((EndpointDesc.bmAttributes & 3) == 2)
PSPRINTF(" BULK");
else
PSPRINTF(" INTR");
PSPRINTF(", Packet Size %d, Interval %d\n",
EndpointDesc.wMaxPacketSize_high*256 +
EndpointDesc.wMaxPacketSize_low,
EndpointDesc.bInterval);
if (EndPointCount > InterfaceDesc.bNumEndpoints) {
PSPRINTF("End point no. %d > NumEndpoints %d\n",
EndPointCount, InterfaceDesc.bNumEndpoints);
}
#endif
if (MassStorage.needClass && MassStorage.Config) {
if ((EndpointDesc.bmAttributes & 3) == 2) {
if (EndpointDesc.bEPAddress & 0x80) {
if (MassStorage.ep_in) {
VPRINT("multiple BULK IN endpoints\n");
MassStorage.Config = 0;
}
else {
MassStorage.ep_in = EndpointDesc.bEPAddress & 0x7f;
MassStorage.ep_in_pksize =
EndpointDesc.wMaxPacketSize_low +
256*EndpointDesc.wMaxPacketSize_high;
}
}
else {
if (MassStorage.ep_out) {
VPRINT("multiple BULK OUT endpoints\n");
MassStorage.Config = 0;
}
else {
MassStorage.ep_out = EndpointDesc.bEPAddress & 0x7f;
MassStorage.ep_out_pksize =
EndpointDesc.wMaxPacketSize_low +
256*EndpointDesc.wMaxPacketSize_high;
}
}
}
else if ((EndpointDesc.bmAttributes & 3) == 3 &&
(EndpointDesc.bEPAddress & 0x80))
{
if (MassStorage.ep_intr) {
VPRINT("multiple INTERRUPT IN endpoints\n");
MassStorage.Config = 0;
}
else {
MassStorage.ep_intr = EndpointDesc.bEPAddress & 0x7f;
MassStorage.ep_intr_pksize =
EndpointDesc.wMaxPacketSize_low +
256*EndpointDesc.wMaxPacketSize_high;
}
}
}
if (StillImage.needClass && StillImage.Config) {
if ((EndpointDesc.bmAttributes & 3) == 2) {
if (EndpointDesc.bEPAddress & 0x80) {
if (StillImage.ep_in) {
VPRINT("multiple BULK IN endpoints\n");
StillImage.Config = 0;
}
else {
StillImage.ep_in = EndpointDesc.bEPAddress & 0x7f;
StillImage.ep_in_pksize =
EndpointDesc.wMaxPacketSize_low +
256*EndpointDesc.wMaxPacketSize_high;
}
}
else {
if (StillImage.ep_out) {
VPRINT("multiple BULK OUT endpoints\n");
StillImage.Config = 0;
}
else {
StillImage.ep_out = EndpointDesc.bEPAddress & 0x7f;
StillImage.ep_out_pksize =
EndpointDesc.wMaxPacketSize_low +
256*EndpointDesc.wMaxPacketSize_high;
}
}
}
else if ((EndpointDesc.bmAttributes & 3) == 3 &&
(EndpointDesc.bEPAddress & 0x80))
{
if (StillImage.ep_intr) {
VPRINT("multiple INTERRUPT IN endpoints\n");
StillImage.Config = 0;
}
else {
StillImage.ep_intr = EndpointDesc.bEPAddress & 0x7f;
StillImage.ep_intr_pksize =
EndpointDesc.wMaxPacketSize_low +
256*EndpointDesc.wMaxPacketSize_high;
StillImage.ep_intr_pollms = EndpointDesc.bInterval;
}
}
}
break;
case HID_TYPE:
if (bf[i] != 9) {
VPRINT("Bad HID desc, size %d\n", bf[i]);
return FALSE;
}
VPRINT("\n HID Descriptor %s\n", (gotIface ? "" : "ignored"));
break;
default:
VPRINT("\n Descriptor type %d ignored.\n", bf[i+1]);
gotIface = FALSE;
break;
}
i += bf[i];
}
#if USBH_VERBOSE
PSPRINTF("****************************************************\n");
if (StillImage.Config) {
PSPRINTF("Still Image Class:\n");
PSPRINTF("Configuration %d, interface %d [alternate %d]\n",
StillImage.Config, StillImage.iface, StillImage.ifaceAlt);
PSPRINTF("IN EP%d [%d], OUT EP%d [%d], INTR EP%d [%d] %d msec. polling\n",
StillImage.ep_in, StillImage.ep_in_pksize,
StillImage.ep_out, StillImage.ep_out_pksize,
StillImage.ep_intr, StillImage.ep_intr_pksize,
StillImage.ep_intr_pollms);
}
if (MassStorage.Config) {
PSPRINTF("Mass Storage Class:\n");
PSPRINTF("Config %d, interface %d [a %d], in %d [%d], out %d [%d]\n",
MassStorage.Config, MassStorage.iface, MassStorage.ifaceAlt,
MassStorage.ep_in, MassStorage.ep_in_pksize,
MassStorage.ep_out, MassStorage.ep_out_pksize);
}
#endif
return TRUE;
}
static void reset_the_device(void)
{
/* Disable and clear all interrupts */
*regINT_ENB = 0;
*regINT_STAT = 0xFF;
/* Reset the device */
usb_host.cur_pipe = NULL;
pipe[0].pksize = FS_CTRL_PKCT_SIZE;
usb_host.USB_addr = 0;
*regADDR = 0;
/* Assert reset on the USB */
*regCTL = CTRL_HOST_NO_SOF | CTRL_RESET;
/* Delay 55 msec. for the reset process to complete */
TaskSleep(&reset_delay);
/* Set the ODD/EVEN BDT to even */
usb_host.even_odd_OUT = BDT_OUT_BIT;
usb_host.even_odd_IN = BDT_IN_BIT;
/*
* Set SOF threshold so we are guaranteed to have enough time for
* any transaction to complete (including ACK or NAK) without reaching
* the time to send the next Start-of-frame packet.
*/
*regSOF_THLD = SOF_THRESHOLD;
/* End the reset , clear ODD bit and enable host */
*regCTL = CTRL_ODD_RST | CTRL_HOST_SOF;
/* Delay 15 msec. for the reset recovery period */
TaskSleep(&recover_delay);
usb_host.reset_required = FALSE;
}
static Uint8 USB_Request(Uint32 *rstatus)
{
Sint32 sem_status, tick = 0;
Boolean STALLflag;
Uint8 code;
STALLflag = FALSE;
while (TRUE) {
if (usb_host.reset_required || !g_powerOn) {
*rstatus = (USBH_ERROR << 24);
return USBH_ERROR;
}
/*
* Stay suspended until awakened by the HISR (High Level Interrupt
* Service Routine), but don't go to sleep if tick != usb_host.tick.
* This means that an interrupt came in with more data after we
* finished processing but, since we were awake at the time, the
* interrupt routine did not signal the semaphore. So if we were
* to go to sleep now we might not be reawakened for a long time,
* if at all.
*/
if (tick == usb_host.tick) {
usb_host.sleeping = TRUE;
/* Test again in case interrupt came in before setting sleep flag */
if (tick == usb_host.tick) {
sem_status = TaskSemWait(USBHSemaphore);
ASSERT(sem_status >= 0);
}
usb_host.sleeping = FALSE;
}
tick = usb_host.tick;
while (usb_host.outx != usb_host.inx) {
DEBUG_DUMP();
*rstatus = usb_host.code_status_error[usb_host.outx];
code = _CODE(*rstatus);
ARM_INTS_OFF
if (++usb_host.outx == CODE_CNT)
usb_host.outx = 0;
ARM_INTS_ON
if (code == USBH_STALL) {
volatile PIPE_STRUCT *pipe;
if (usb_host.cur_pipe) {
#ifdef MSCLASS_HOST_PASSTHROUGH
static Uint8 ClrFeatureEP[8] = {2, 1, 0, 0, 0, 0, 0, 0};
STALLflag = TRUE;
pipe = usb_host.cur_pipe;
if (pipe->EP) {
/* Send CLEAR_FEATURE */
ClrFeatureEP[wIndex_low] = pipe->EP;
if (pipe->pipe_type != PIPE_OUT)
ClrFeatureEP[wIndex_low] |= 0x80;
VPRINT("CLEAR STALL: %06x\n", (*rstatus & 0xffffff));
USB_device_request(ClrFeatureEP);
}
#else
pipe = usb_host.cur_pipe;
if (pipe->EP && pipe->EP != pipe[PIPE_INT].EP) {
/*
* Don't Clear Endpoint
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -