Merge branch 'master' into usbkb_sauter
authorBernhard Urban <lewurm@gmx.net>
Wed, 23 Sep 2009 15:42:23 +0000 (17:42 +0200)
committerBernhard Urban <lewurm@gmx.net>
Wed, 23 Sep 2009 15:42:23 +0000 (17:42 +0200)
Conflicts:
Makefile
gecko.c
hollywood.h
main.c

36 files changed:
.gitignore
Makefile
bootmii_ppc.h
exception.c
hollywood.h
irq.c [new file with mode: 0644]
irq.h [new file with mode: 0644]
main.c
usb/AUTHORS [new file with mode: 0644]
usb/COPYING [new file with mode: 0644]
usb/Makefile [new file with mode: 0644]
usb/README [new file with mode: 0644]
usb/core/README [new file with mode: 0644]
usb/core/core.c [new file with mode: 0644]
usb/core/core.h [new file with mode: 0644]
usb/core/usb.c [new file with mode: 0644]
usb/core/usb.h [new file with mode: 0644]
usb/drivers/class/hid.c [new file with mode: 0644]
usb/drivers/class/hid.h [new file with mode: 0644]
usb/drivers/class/hub.c [new file with mode: 0644]
usb/drivers/class/hub.h [new file with mode: 0644]
usb/drivers/class/storage.c [new file with mode: 0644]
usb/drivers/class/storage.h [new file with mode: 0644]
usb/drivers/mon/mon.c [new file with mode: 0644]
usb/drivers/mon/mon.h [new file with mode: 0644]
usb/drivers/skeleton.c [new file with mode: 0644]
usb/host/host.h [new file with mode: 0644]
usb/host/ohci.c [new file with mode: 0644]
usb/host/ohci.h [new file with mode: 0644]
usb/lib/list.c [new file with mode: 0644]
usb/lib/list.h [new file with mode: 0644]
usb/uclibusb/ft232.c [new file with mode: 0644]
usb/uclibusb/ft232.h [new file with mode: 0644]
usb/usbspec/request.c [new file with mode: 0644]
usb/usbspec/request.h [new file with mode: 0644]
usb/usbspec/usb11spec.h [new file with mode: 0644]

index ad0bbdf1f999b0044977523e60a9bf9496302982..daaf8b9f20190d7fee64a0ac1f049e9edc46c00f 100644 (file)
@@ -1,5 +1,6 @@
 git_version.h
 *.d
+.deps/*.d
 *.bin
 *.elf
 *.map
index 39a27fff227c54c5f16c3183b8ba11d32ee64475..a7d144b9fabeee99e180e4fb441dd55fe62fbb20 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 include broadway.mk
 
-DEFINES = -DLACKS_SYS_TYPES_H -DLACKS_ERRNO_H -DLACKS_STDLIB_H -DLACKS_STRING_H -DLACKS_STRINGS_H -DLACKS_UNISTD_H
+DEFINES = -DLACKS_SYS_TYPES_H -DLACKS_ERRNO_H -DLACKS_STDLIB_H -DLACKS_STRING_H -DLACKS_STRINGS_H -DLACKS_UNISTD_H -DCAN_HAZ_IRQ
 LDSCRIPT = mini.ld
 LIBS = -lgcc
 
@@ -9,7 +9,9 @@ TARGET = ppcboot.elf
 OBJS = realmode.o crt0.o main.o string.o sync.o time.o printf.o input.o \
        exception.o exception_2200.o malloc.o gecko.o video_low.o \
        ipc.o mini_ipc.o nandfs.o ff.o diskio.o fat.o font.o console.o \
-       sha1.o
+       irq.o sha1.o
+
+include usb/Makefile
 
 include common.mk
 
index 49de6b5569b1132089ae506997dbeab1e9df01b3..4f69d44783df15ab6cb4ccf4c444f977ed25414b 100644 (file)
@@ -45,6 +45,16 @@ static inline void write32(u32 addr, u32 x)
        asm("stw %0,0(%1) ; eieio" : : "r"(x), "b"(0xc0000000 | addr));
 }
 
+static inline void set32(u32 addr, u32 set)
+{
+       write32(addr, read32(addr) | set);
+}
+
+static inline void clear32(u32 addr, u32 clear)
+{
+       write32(addr, read32(addr)&(~clear));
+}
+
 static inline void mask32(u32 addr, u32 clear, u32 set)
 {
        write32(addr, (read32(addr)&(~clear)) | set);
@@ -108,6 +118,7 @@ void exception_init(void);
 
 void gecko_init(void);
 int printf(const char *fmt, ...);
+void hexdump(void *d, int len);
 
 
 // Debug: blink the tray led.
index 095de44507780d28a82b3aed68c741d17f825036..f42b78be2da341bf1f7eeef5aa477967bc82394b 100644 (file)
@@ -3,6 +3,8 @@
        Requires mini.
 
 Copyright (C) 2008             Segher Boessenkool <segher@kernel.crashing.org>
+Copyright (C) 2009             Bernhard Urban <lewurm@gmx.net>
+Copyright (C) 2009             Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
 
 # This code is licensed to you under the terms of the GNU GPL, version 2;
 # see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
@@ -11,34 +13,51 @@ Copyright (C) 2008          Segher Boessenkool <segher@kernel.crashing.org>
 #include "bootmii_ppc.h"
 
 #include "string.h"
+#include "irq.h"
+#include "hollywood.h"
 
 extern char exception_2200_start, exception_2200_end;
 
 void exception_handler(int exception)
 {
-       u32 *x;
-       u32 i;
+       u32 cookie = irq_kill();
+       // check if the exception was actually an external interrupt
+       if (exception == 0x500) {
+               irq_handler();
+       }
 
-       printf("\nException %04x occurred!\n", exception);
+       // check if exception happened due to the decrementer
+       else if (exception == 0x900) {
+               //printf("\nDecrementer exception occured - who cares?\n");
+       }
 
-       x = (u32 *)0x80002000;
+       else {
+               u32 *x;
+               u32 i;
 
-       printf("\n R0..R7    R8..R15  R16..R23  R24..R31\n");
-       for (i = 0; i < 8; i++) {
-               printf("%08x  %08x  %08x  %08x\n", x[0], x[8], x[16], x[24]);
-               x++;
-       }
-       x = (u32 *)0x80002080;
+               printf("\nException %04X occurred!\n", exception);
+
+               x = (u32 *)0x80002000;
+
+               printf("\n R0..R7    R8..R15  R16..R23  R24..R31\n");
+               for (i = 0; i < 8; i++) {
+                       printf("%08x  %08x  %08x  %08x\n", x[0], x[8], x[16], x[24]);
+                       x++;
+               }
+               x = (u32 *)0x80002080;
+
+               printf("\n CR/XER    LR/CTR  SRR0/SRR1 DAR/DSISR\n");
+               for (i = 0; i < 2; i++) {
+                       printf("%08x  %08x  %08x  %08x\n", x[0], x[2], x[4], x[6]);
+                       x++;
+               }
 
-       printf("\n CR/XER    LR/CTR  SRR0/SRR1 DAR/DSISR\n");
-       for (i = 0; i < 2; i++) {
-               printf("%08x  %08x  %08x  %08x\n", x[0], x[2], x[4], x[6]);
-               x++;
+               // Hang.
+               for (;;)
+                       ;
        }
 
-       // Hang.
-       for (;;)
-               ;
+       irq_restore(cookie);
 }
 
 void exception_init(void)
index 3f2dde48eb0ee7a0b0d0d6d3c9574882a29b78e0..e957e99cc67c44dbaeeafe3f3b6a6209230d5abb 100644 (file)
@@ -140,66 +140,39 @@ Copyright (C) 2008, 2009  John Kelley <wiidev@kelley.ca>
 #define                SDHC_REG_BASE           0xd070000
 
 /* OHCI0 Registers */
-
 #define        OHCI0_REG_BASE          0xd050000
 
-#define        OHCI0_HC_REVISION                       (OHCI0_REG_BASE + 0x00)
-#define        OHCI0_HC_CONTROL                        (OHCI0_REG_BASE + 0x04)
-#define        OHCI0_HC_COMMAND_STATUS         (OHCI0_REG_BASE + 0x08)
-#define        OHCI0_HC_INT_STATUS             (OHCI0_REG_BASE + 0x0C)
-
-#define        OHCI0_HC_INT_ENABLE             (OHCI0_REG_BASE + 0x10)
-#define        OHCI0_HC_INT_DISABLE            (OHCI0_REG_BASE + 0x14)
-#define        OHCI0_HC_HCCA                           (OHCI0_REG_BASE + 0x18)
-#define        OHCI0_HC_PERIOD_CURRENT_ED      (OHCI0_REG_BASE + 0x1C)
-
-#define        OHCI0_HC_CTRL_HEAD_ED           (OHCI0_REG_BASE + 0x20)
-#define        OHCI0_HC_CTRL_CURRENT_ED        (OHCI0_REG_BASE + 0x24)
-#define        OHCI0_HC_BULK_HEAD_ED           (OHCI0_REG_BASE + 0x28)
-#define        OHCI0_HC_BULK_CURRENT_ED        (OHCI0_REG_BASE + 0x2C)
-
-#define        OHCI0_HC_DONE_HEAD                      (OHCI0_REG_BASE + 0x30)
-#define        OHCI0_HC_FM_INTERVAL            (OHCI0_REG_BASE + 0x34)
-#define        OHCI0_HC_FM_REMAINING           (OHCI0_REG_BASE + 0x38)
-#define        OHCI0_HC_FM_NUMBER                      (OHCI0_REG_BASE + 0x3C)
-
-#define        OHCI0_HC_PERIODIC_START         (OHCI0_REG_BASE + 0x40)
-#define        OHCI0_HC_LS_THRESHOLD           (OHCI0_REG_BASE + 0x44)
-#define        OHCI0_HC_RH_DESCRIPTOR_A        (OHCI0_REG_BASE + 0x48)
-#define        OHCI0_HC_RH_DESCRIPTOR_B        (OHCI0_REG_BASE + 0x4C)
-
-#define        OHCI0_HC_RH_STATUS                      (OHCI0_REG_BASE + 0x50)
-
 /* OHCI1 Registers */
-
 #define        OHCI1_REG_BASE          0xd060000
 
-#define        OHCI1_HC_REVISION                       (OHCI1_REG_BASE + 0x00)
-#define        OHCI1_HC_CONTROL                        (OHCI1_REG_BASE + 0x04)
-#define        OHCI1_HC_COMMAND_STATUS         (OHCI1_REG_BASE + 0x08)
-#define        OHCI1_HC_INT_STATUS             (OHCI1_REG_BASE + 0x0C)
-
-#define        OHCI1_HC_INT_ENABLE             (OHCI1_REG_BASE + 0x10)
-#define        OHCI1_HC_INT_DISABLE            (OHCI1_REG_BASE + 0x14)
-#define        OHCI1_HC_HCCA                           (OHCI1_REG_BASE + 0x18)
-#define        OHCI1_HC_PERIOD_CURRENT_ED      (OHCI1_REG_BASE + 0x1C)
-
-#define        OHCI1_HC_CTRL_HEAD_ED           (OHCI1_REG_BASE + 0x20)
-#define        OHCI1_HC_CTRL_CURRENT_ED        (OHCI1_REG_BASE + 0x24)
-#define        OHCI1_HC_BULK_HEAD_ED           (OHCI1_REG_BASE + 0x28)
-#define        OHCI1_HC_BULK_CURRENT_ED        (OHCI1_REG_BASE + 0x2C)
-
-#define        OHCI1_HC_DONE_HEAD                      (OHCI1_REG_BASE + 0x30)
-#define        OHCI1_HC_FM_INTERVAL            (OHCI1_REG_BASE + 0x34)
-#define        OHCI1_HC_FM_REMAINING           (OHCI1_REG_BASE + 0x38)
-#define        OHCI1_HC_FM_NUMBER                      (OHCI1_REG_BASE + 0x3C)
-
-#define        OHCI1_HC_PERIODIC_START         (OHCI1_REG_BASE + 0x40)
-#define        OHCI1_HC_LS_THRESHOLD           (OHCI1_REG_BASE + 0x44)
-#define        OHCI1_HC_RH_DESCRIPTOR_A        (OHCI1_REG_BASE + 0x48)
-#define        OHCI1_HC_RH_DESCRIPTOR_B        (OHCI1_REG_BASE + 0x4C)
-
-#define        OHCI1_HC_RH_STATUS                      (OHCI1_REG_BASE + 0x50)
+#define        OHCI_HC_REVISION                        0x00
+#define        OHCI_HC_CONTROL                         0x04
+#define        OHCI_HC_COMMAND_STATUS          0x08
+#define        OHCI_HC_INT_STATUS                      0x0C
+
+#define        OHCI_HC_INT_ENABLE                      0x10
+#define        OHCI_HC_INT_DISABLE             0x14
+#define        OHCI_HC_HCCA                            0x18
+#define        OHCI_HC_PERIOD_CURRENT_ED       0x1C
+
+#define        OHCI_HC_CTRL_HEAD_ED            0x20
+#define        OHCI_HC_CTRL_CURRENT_ED         0x24
+#define        OHCI_HC_BULK_HEAD_ED            0x28
+#define        OHCI_HC_BULK_CURRENT_ED         0x2C
+
+#define        OHCI_HC_DONE_HEAD                       0x30
+#define        OHCI_HC_FM_INTERVAL             0x34
+#define        OHCI_HC_FM_REMAINING            0x38
+#define        OHCI_HC_FM_NUMBER                       0x3C
+
+#define        OHCI_HC_PERIODIC_START          0x40
+#define        OHCI_HC_LS_THRESHOLD            0x44
+#define        OHCI_HC_RH_DESCRIPTOR_A         0x48
+#define        OHCI_HC_RH_DESCRIPTOR_B         0x4C
+
+#define        OHCI_HC_RH_STATUS                       0x50
+#define        OHCI_HC_RH_PORT_STATUS_1        0x54
+#define        OHCI_HC_RH_PORT_STATUS_2        0x58
 
 /* EHCI Registers */
 #define        EHCI_REG_BASE           0xd040000
diff --git a/irq.c b/irq.c
new file mode 100644 (file)
index 0000000..1217ee2
--- /dev/null
+++ b/irq.c
@@ -0,0 +1,165 @@
+/*
+       ppcskel - a Free Software replacement for the Nintendo/BroadOn IOS.
+       IRQ support
+
+Copyright (C) 2009             Bernhard Urban <lewurm@gmx.net>
+Copyright (C) 2009             Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
+
+# This code is licensed to you under the terms of the GNU GPL, version 2;
+# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*/
+
+#include "irq.h"
+#include "hollywood.h"
+#include "ipc.h"
+#include "bootmii_ppc.h"
+#include "usb/host/host.h"
+#include "mini_ipc.h"
+
+void show_frame_no(void);
+
+void irq_initialize(void)
+{
+       // clear flipper-pic (processor interface)
+       write32(BW_PI_IRQMASK, 0);
+       write32(BW_PI_IRQFLAG, 0xffffffff);
+
+       // clear hollywood-pic
+       write32(HW_PPCIRQMASK, 0);
+       write32(HW_PPCIRQFLAG, 0xffffffff);
+
+       /* ??? -- needed?!
+        * in mini they do
+        *
+        * write32(HW_ARMIRQMASK+0x04, 0);
+        * write32(HW_ARMIRQMASK+0x20, 0);
+        *
+        *
+        * may it's here following; on the other 
+        * hand it's already done by mini...
+        *
+        * write32(HW_PPCIRQMASK+0x04+0x08, 0);
+        * write32(HW_PPCIRQMASK+0x20+0x08, 0);
+        */
+
+       _CPU_ISR_Enable()
+}
+
+void irq_shutdown(void)
+{
+       write32(HW_PPCIRQMASK, 0);
+       write32(HW_PPCIRQFLAG, 0xffffffff);
+       (void) irq_kill();
+}
+
+void irq_handler(void)
+{
+       u32 enabled = read32(BW_PI_IRQMASK);
+       u32 flags = read32(BW_PI_IRQFLAG);
+
+       flags = flags & enabled;
+
+       if (flags & (1<<BW_PI_IRQ_RESET)) { 
+               write32(BW_PI_IRQFLAG, 1<<BW_PI_IRQ_RESET);
+               boot2_run(1,2); //sysmenu
+       }
+
+       if (flags & (1<<BW_PI_IRQ_HW)) { //HW-PIC IRQ
+               u32 hw_enabled = read32(HW_PPCIRQMASK);
+               u32 hw_flags = read32(HW_PPCIRQFLAG);
+
+               //printf("In IRQ handler: 0x%08x 0x%08x 0x%08x\n", hw_enabled, hw_flags, hw_flags & hw_enabled);
+
+               hw_flags = hw_flags & hw_enabled;
+
+               if(hw_flags & IRQF_TIMER) {
+                       write32(HW_PPCIRQFLAG, IRQF_TIMER);
+               }
+               if(hw_flags & IRQF_NAND) {
+                       //              printf("IRQ: NAND\n");
+                       // hmmm... should be done by mini?
+                       write32(NAND_CMD, 0x7fffffff); // shut it up
+                       write32(HW_PPCIRQFLAG, IRQF_NAND);
+                       //nand_irq();
+               }
+               if(hw_flags & IRQF_GPIO1B) {
+                       //              printf("IRQ: GPIO1B\n");
+                       // hmmm... should be done by mini?
+                       write32(HW_GPIO1BINTFLAG, 0xFFFFFF); // shut it up
+                       write32(HW_PPCIRQFLAG, IRQF_GPIO1B);
+               }
+               if(hw_flags & IRQF_GPIO1) {
+                       //              printf("IRQ: GPIO1\n");
+                       // hmmm... should be done by mini?
+                       write32(HW_GPIO1INTFLAG, 0xFFFFFF); // shut it up
+                       write32(HW_PPCIRQFLAG, IRQF_GPIO1);
+               }
+               if(hw_flags & IRQF_RESET) {
+                       //              printf("IRQ: RESET\n");
+                       write32(HW_PPCIRQFLAG, IRQF_RESET);
+               }
+               if(hw_flags & IRQF_IPC) {
+                       //printf("IRQ: IPC\n");
+                       //not necessary here?
+                       //ipc_irq();
+                       write32(HW_PPCIRQFLAG, IRQF_IPC);
+               }
+               if(hw_flags & IRQF_AES) {
+                       //              printf("IRQ: AES\n");
+                       write32(HW_PPCIRQFLAG, IRQF_AES);
+               }
+               if (hw_flags & IRQF_SDHC) {
+                       //              printf("IRQ: SDHC\n");
+                       write32(HW_PPCIRQFLAG, IRQF_SDHC);
+                       //sdhc_irq();
+               }
+               if (hw_flags & IRQF_OHCI0) {
+                       hcdi_irq(OHCI0_REG_BASE);
+                       write32(HW_PPCIRQFLAG, IRQF_OHCI0);
+               }
+               if (hw_flags & IRQF_OHCI1) {
+                       hcdi_irq(OHCI1_REG_BASE);
+                       write32(HW_PPCIRQFLAG, IRQF_OHCI1);
+               }
+
+               hw_flags &= ~IRQF_ALL;
+               if(hw_flags) {
+                       printf("IRQ: unknown 0x%08x\n", hw_flags);
+                       write32(HW_PPCIRQFLAG, hw_flags);
+               }
+
+               // not necessary here, but "cleaner"?
+               write32(BW_PI_IRQFLAG, 1<<BW_PI_IRQ_HW);
+       }
+}
+
+void irq_bw_enable(u32 irq)
+{
+       set32(BW_PI_IRQMASK, 1<<irq);
+}
+
+void irq_bw_disable(u32 irq) {
+       clear32(BW_PI_IRQMASK, 1<<irq);
+}
+
+void irq_hw_enable(u32 irq)
+{
+       set32(HW_PPCIRQMASK, 1<<irq);
+}
+
+void irq_hw_disable(u32 irq)
+{
+       clear32(HW_PPCIRQMASK, 1<<irq);
+}
+
+u32 irq_kill() {
+       u32 cookie;
+       _CPU_ISR_Disable(cookie);
+       return cookie;
+}
+
+void irq_restore(u32 cookie) {
+       _CPU_ISR_Restore(cookie);
+       _CPU_ISR_Enable(); //wtf :/
+}
+
diff --git a/irq.h b/irq.h
new file mode 100644 (file)
index 0000000..2e09926
--- /dev/null
+++ b/irq.h
@@ -0,0 +1,143 @@
+/*
+       ppcskel - a Free Software replacement for the Nintendo/BroadOn IOS.
+       IRQ support
+
+Copyright (C) 2009             Bernhard Urban <lewurm@gmx.net>
+Copyright (C) 2009             Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
+
+# This code is licensed to you under the terms of the GNU GPL, version 2;
+# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*/
+
+#ifndef __IRQ_H__
+#define __IRQ_H__
+
+#include "types.h"
+
+#ifdef CAN_HAZ_IRQ
+#define IRQ_TIMER      0
+#define IRQ_NAND       1
+#define IRQ_AES                2
+#define IRQ_SHA1       3
+#define IRQ_EHCI       4
+#define IRQ_OHCI0      5
+#define IRQ_OHCI1      6
+#define IRQ_SDHC       7
+#define IRQ_WIFI       8
+#define IRQ_GPIO1B     10
+#define IRQ_GPIO1      11
+#define IRQ_RESET      17
+#define IRQ_PPCIPC     30
+#define IRQ_IPC                31
+
+#define IRQF_TIMER     (1<<IRQ_TIMER)
+#define IRQF_NAND      (1<<IRQ_NAND)
+#define IRQF_AES       (1<<IRQ_AES)
+#define IRQF_SDHC      (1<<IRQ_SDHC)
+#define IRQF_GPIO1B    (1<<IRQ_GPIO1B)
+#define IRQF_GPIO1     (1<<IRQ_GPIO1)
+#define IRQF_RESET     (1<<IRQ_RESET)
+#define IRQF_IPC       (1<<IRQ_IPC)
+#define IRQF_OHCI0     (1<<IRQ_OHCI0)
+#define IRQF_OHCI1     (1<<IRQ_OHCI1)
+
+#define IRQF_ALL       ( \
+       IRQF_TIMER|IRQF_NAND|IRQF_GPIO1B|IRQF_GPIO1| \
+       IRQF_RESET|IRQF_IPC|IRQF_AES|IRQF_SDHC| \
+       IRQF_OHCI0|IRQF_OHCI1 \
+       )
+
+/* broadway.h? :o */
+/* broadway processor interface registers */
+#define BW_PI_IRQFLAG (0x0c003000)
+#define BW_PI_IRQMASK (0x0c003004)
+
+// http://hitmen.c02.at/files/yagcd/yagcd/chap5.html#sec5.4
+#define BW_PI_IRQ_RESET        1
+#define BW_PI_IRQ_DI           2
+#define BW_PI_IRQ_SI           3
+#define BW_PI_IRQ_EXI          4
+#define BW_PI_IRQ_AI           5
+#define BW_PI_IRQ_DSP          6
+#define BW_PI_IRQ_MEM          7
+#define BW_PI_IRQ_VI           8
+#define BW_PI_IRQ_PE_TOKEN     9
+#define BW_PI_IRQ_PE_FINISH    10
+#define BW_PI_IRQ_CP           11
+#define BW_PI_IRQ_DEBUG        12
+#define BW_PI_IRQ_HSP          13
+#define BW_PI_IRQ_HW           14 //hollywood pic
+
+/* stolen from libogc - gc/ogc/machine/processor.h */
+#define _CPU_ISR_Enable() \
+       { register u32 _val = 0; \
+         __asm__ __volatile__ ( \
+               "mfmsr %0\n" \
+               "ori %0,%0,0x8000\n" \
+               "mtmsr %0" \
+               : "=&r" ((_val)) : "0" ((_val)) \
+         ); \
+       }
+
+#define _CPU_ISR_Disable( _isr_cookie ) \
+  { register u32 _disable_mask = 0; \
+       _isr_cookie = 0; \
+    __asm__ __volatile__ ( \
+         "mfmsr %0\n" \
+         "rlwinm %1,%0,0,17,15\n" \
+         "mtmsr %1\n" \
+         "extrwi %0,%0,1,16" \
+         : "=&r" ((_isr_cookie)), "=&r" ((_disable_mask)) \
+         : "0" ((_isr_cookie)), "1" ((_disable_mask)) \
+       ); \
+  }
+
+#define _CPU_ISR_Restore( _isr_cookie )  \
+  { register u32 _enable_mask = 0; \
+       __asm__ __volatile__ ( \
+    "    cmpwi %0,0\n" \
+       "    beq 1f\n" \
+       "    mfmsr %1\n" \
+       "    ori %1,%1,0x8000\n" \
+       "    mtmsr %1\n" \
+       "1:" \
+       : "=r"((_isr_cookie)),"=&r" ((_enable_mask)) \
+       : "0"((_isr_cookie)),"1" ((_enable_mask)) \
+       ); \
+  }
+
+void irq_initialize(void);
+void irq_shutdown(void);
+
+void irq_handler(void);
+
+void irq_bw_enable(u32 irq);
+void irq_bw_disable(u32 irq);
+void irq_hw_enable(u32 irq);
+void irq_hw_disable(u32 irq);
+
+u32 irq_kill(void);
+void irq_restore(u32 cookie);
+
+/* TODO: port to ppc 
+static inline void irq_wait(void)
+{
+       u32 data = 0;
+       __asm__ volatile ( "mcr\tp15, 0, %0, c7, c0, 4" : : "r" (data) );
+}
+*/
+
+#endif
+
+#else
+// stub functions allow us to avoid sprinkling other code with ifdefs
+static inline u32 irq_kill(void) {
+       return 0;
+}
+
+static inline void irq_restore(u32 cookie) {
+       (void)cookie;
+}
+#endif
+
+
diff --git a/main.c b/main.c
index 3e186f3f13505102362c6a0baa1af280907f7792..451b87dba0a95145ca920c0b972d0ba88ca8d9ef 100644 (file)
--- a/main.c
+++ b/main.c
@@ -24,6 +24,9 @@ Copyright (C) 2009              John Kelley <wiidev@kelley.ca>
 #include "video_low.h"
 #include "input.h"
 #include "console.h"
+#include "irq.h"
+#include "usb/core/core.h"
+#include "usb/drivers/class/hid.h"
 #include "sha1.h"
 #include "hollywood.h"
 
@@ -84,8 +87,13 @@ int main(void)
        exception_init();
        dsp_reset();
 
-       // clear interrupt mask
-       write32(0x0c003004, 0);
+       irq_initialize();
+       irq_bw_enable(BW_PI_IRQ_RESET);
+       irq_bw_enable(BW_PI_IRQ_HW); //hollywood pic
+       /* external ohci */
+       irq_hw_enable(IRQ_OHCI0);
+       /* internal ohci */
+       //irq_hw_enable(IRQ_OHCI1);
 
        ipc_initialize();
        ipc_slowping();
@@ -111,11 +119,57 @@ int main(void)
                        ; // better ideas welcome!
        }
 
+       /* external ohci */
+       usb_init(OHCI0_REG_BASE);
+
+       /* internal ohci */
+       //usb_init(OHCI1_REG_BASE);
+
+       /* load HID keyboard driver */
+       usb_hidkb_init();
+
+       /* you are welcome to make this nice :) */
+       char str[7];
+       u16 i, j, y=20, x=20;
+       struct kbrep *k;
+
+       while(1) {
+               memset(str, '\0', 8);
+               j=0;
+               k = usb_hidkb_getChars();
+               for(i=0; k->keys[i]>0; i++) {
+                       if(x>650) {
+                               x = 20;
+                               y += 15;
+                       }
+                       if(y>440) {
+                               y=20;
+                       }
+                       if((k->keys[i] >= 4) && k->keys[i] <= 4+'z'-'a') {
+                               str[j] = k->keys[i] - 4 + 'a';
+                       } 
+                       else if (k->keys[i] == 0x28) {
+                               y += 15;
+                               x = 20;
+                       }
+                       j++;
+               }
+               if(j > 0) {
+                       print_str_noscroll(x, y, str);
+                       printf("y: %d\n", y);
+               }
+               while(j--) {
+                       x += 13;
+               }
+       }
+
+#if 0
        printf("===============================\n");
 
        SHA1TestCases();
 
        printf("bye, world!\n");
+#endif
 
        return 0;
 }
diff --git a/usb/AUTHORS b/usb/AUTHORS
new file mode 100644 (file)
index 0000000..a4d30e7
--- /dev/null
@@ -0,0 +1,3 @@
+Benedikt Sauter, sauter@ixbat.de
+Bernhard Urban, lewurm@gmx.net
+Sebastian Falbesoner, sebastian.falbesoner@gmail.com
diff --git a/usb/COPYING b/usb/COPYING
new file mode 100644 (file)
index 0000000..b04f484
--- /dev/null
@@ -0,0 +1,28 @@
+Copyright (c) 2006, Benedikt Sauter <sauter@ixbat.de>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions 
+are met:
+
+    * Redistributions of source code must retain the above copyright 
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above 
+      copyright notice, this list of conditions and the following 
+      disclaimer in the documentation and/or other materials provided 
+      with the distribution.
+    * Neither the name of the FH Augsburg nor the names of its 
+      contributors may be used to endorse or promote products derived 
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/usb/Makefile b/usb/Makefile
new file mode 100644 (file)
index 0000000..37803e1
--- /dev/null
@@ -0,0 +1,15 @@
+#tmp...
+CFLAGS += -Wno-unused-parameter 
+
+#debug flags; DU = Debug USB
+#CFLAGS += -D _DU_OHCI_F #fire @ u/h/ohci.c
+CFLAGS += -D _DU_OHCI_F_HALT #halted @ u/h/ohci.c
+#CFLAGS += -D _DU_OHCI_Q #enqueue @ u/h/ohci.c
+#CFLAGS += -D _DU_OHCI_RH #roothub @ u/h/ohci.c
+CFLAGS += -D _DU_CORE #@ u/c/core.c
+#CFLAGS += -D _DU_CORE_ADD #@ u/c/core.c
+CFLAGS += -D _DU_USB #@ u/c/usb.c
+
+OBJS += usb/host/ohci.o usb/core/core.o usb/core/usb.o \
+               usb/lib/list.o usb/usbspec/request.o \
+               usb/drivers/class/hid.o
diff --git a/usb/README b/usb/README
new file mode 100644 (file)
index 0000000..08396ec
--- /dev/null
@@ -0,0 +1 @@
+http://wiibrew.org/wiki/Plugmii
diff --git a/usb/core/README b/usb/core/README
new file mode 100644 (file)
index 0000000..6f4df70
--- /dev/null
@@ -0,0 +1,5 @@
+USB Subsystem
+
+
+
+
diff --git a/usb/core/core.c b/usb/core/core.c
new file mode 100644 (file)
index 0000000..889fba4
--- /dev/null
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 2006, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *      * Redistributions of source code must retain the above copyright 
+ *              notice, this list of conditions and the following disclaimer.
+ *      * Redistributions in binary form must reproduce the above 
+ *              copyright notice, this list of conditions and the following 
+ *              disclaimer in the documentation and/or other materials provided 
+ *              with the distribution.
+ *      * Neither the name of the FH Augsburg nor the names of its 
+ *              contributors may be used to endorse or promote products derived 
+ *              from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+       ppcskel - a Free Software replacement for the Nintendo/BroadOn bootloader.
+       plugmii core
+
+Copyright (C) 2009     Bernhard Urban <lewurm@gmx.net>
+Copyright (C) 2009     Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
+
+# This code is licensed to you under the terms of the GNU GPL, version 2;
+# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*/
+
+#include "core.h"
+#include "../host/host.h"
+#include "usb.h"
+#include "../usbspec/usb11spec.h"
+#include "../lib/list.h"
+#include "../../malloc.h"
+#include "../../bootmii_ppc.h" //printf
+#include "../../string.h" //memset
+
+/**
+ * Initialize USB stack.
+ */
+void usb_init(u32 reg)
+{
+       core.drivers = list_create();
+       core.devices = list_create();
+       core.nextaddress = 1;
+       hcdi_init(reg);
+}
+
+/**
+ * Get next free usb device address.
+ */
+u8 usb_next_address()
+{
+       u8 addr = core.nextaddress;
+       core.nextaddress++;
+       return addr;
+}
+
+
+/**
+ * Call this function periodically for 
+ * control and transfer management.
+ */
+void usb_periodic()
+{
+       // call ever registered driver  
+       struct usb_driver *drv;
+       struct element *iterator = core.drivers->head;
+       while (iterator != NULL) {
+               drv = (struct usb_driver *) iterator->data;
+               drv->check();
+               iterator = iterator->next;
+       }
+}
+
+
+/** 
+ * Enumerate new device and create data structures 
+ * for the core. usb_add_device expected that
+ * the device answers to address zero.
+ */
+struct usb_device *usb_add_device(u8 lowspeed, u32 reg)
+{
+       struct usb_device *dev = (struct usb_device *) malloc(sizeof(struct usb_device));
+       dev->conf = (struct usb_conf *) malloc(sizeof(struct usb_conf));
+       dev->address = 0;
+       dev->fullspeed = lowspeed ? 0 : 1;
+       /* send at first time only 8 bytes for lowspeed devices
+        * 64 bytes for fullspeed
+        */
+       dev->bMaxPacketSize0 = lowspeed ? 8 : 64;
+       dev->ohci = reg;
+
+       dev->epSize[0] = 8;
+       dev->epSize[1] = 64;
+       dev->epSize[2] = 64;
+
+       dev->epTogl[0] = 0;
+       dev->epTogl[1] = 0;
+       dev->epTogl[2] = 0;
+
+       s8 ret;
+       ret = usb_get_desc_dev_simple(dev);
+       if(ret < 0) {
+               return (void*) -1;
+       }
+
+#define WTF
+#ifdef WTF
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lolololool PADDING WTF :O lolololololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lolololool PADDING WTF :O lolololololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lollllool PADDING WTF :O lolololololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lolololool PADDING WTF :O lololoololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lolololool PADDING WTF :O lolololololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lollllool PADDING WTF :O lolololololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lolololool PADDING WTF :O lololoololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lolololool PADDING WTF :O lolololololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lollllool PADDING WTF :O lolololololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lolololool PADDING WTF :O lololoololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lolololool PADDING WTF :O lolololololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lollllool PADDING WTF :O lolololololo \n");
+       printf("lolololool PADDING WTF :O lolololololo \n");
+       printf("lololololool PADDING WTF :O lolololololo \n");
+       printf("lollllool PADDING WTF :O lolololololo \n");
+#endif
+       u8 address = usb_next_address();
+       ret = usb_set_address(dev, address);
+       dev->address = address;
+       printf("set address to %d\n", dev->address);
+
+       /* get device descriptor&co */
+       ret = usb_get_desc_dev(dev);
+       if(ret < 0)
+               return (void*) -1;
+
+       /* print device info */
+       lsusb(dev);
+
+       /* add device to device list */
+       struct element *tmp = (struct element *) malloc(sizeof(struct element));
+       tmp->data = (void *) dev;
+       list_add_tail(core.devices, tmp);
+
+       usb_probe_driver();
+
+       return dev;
+}
+
+void lsusb(struct usb_device *dev)
+{
+       printf("=== Device Descriptor === \n");
+       printf("bLength 0x%02X\n", dev->bLength);
+       printf("bDescriptorType 0x%02X\n", dev->bDeviceClass);
+       printf("bcdUSB 0x%04X\n", dev->bcdUSB);
+       printf("bDeviceClass 0x%02X\n", dev->bDeviceClass);
+       printf("bDeviceSubClass 0x%02X\n", dev->bDeviceSubClass);
+       printf("bDeviceProtocoll 0x%02X\n", dev->bDeviceProtocoll);
+       printf("bMaxPacketSize 0x%02X\n", dev->bMaxPacketSize0);
+       printf("idVendor 0x%04X\n", dev->idVendor);
+       printf("idProduct 0x%04X\n", dev->idProduct);
+       printf("bcdDevice 0x%04X\n", dev->bcdDevice);
+       printf("iManufacturer(0x%02X): \"%s\"\n", dev->iManufacturer, dev->iManufacturer ? usb_get_string_simple(dev, dev->iManufacturer) : "no String");
+       printf("iProduct(0x%02X): \"%s\"\n", dev->iProduct, dev->iProduct ? usb_get_string_simple(dev, dev->iProduct) : "no String");
+       printf("iSerialNumber(0x%02X): \"%s\"\n", dev->iSerialNumber, dev->iSerialNumber ? usb_get_string_simple(dev, dev->iSerialNumber) : "no String");
+       printf("bNumConfigurations 0x%02X\n", dev->bNumConfigurations);
+
+       u8 c, i, e;
+       struct usb_conf *conf = dev->conf;
+       for(c=0; c <= dev->bNumConfigurations; c++) {
+               printf("  === Configuration Descriptor %d ===\n", c+1);
+               printf("  bLength 0x%02X\n", conf->bLength);
+               printf("  bDescriptorType 0x%02X\n", conf->bDescriptorType);
+               printf("  wTotalLength 0x%04X\n", conf->wTotalLength);
+               printf("  bNumInterfaces 0x%02X\n", conf->bNumInterfaces);
+               printf("  bConfigurationValue 0x%02X\n", conf->bConfigurationValue);
+               printf("  iConfiguration (0x%02X): \"%s\"\n", conf->iConfiguration, conf->iConfiguration ? usb_get_string_simple(dev, conf->iConfiguration) : "no String");
+               printf("  bmAttributes 0x%02X\n", conf->bmAttributes);
+               printf("  bMaxPower 0x%02X\n", conf->bMaxPower);
+
+               struct usb_intf *ifs = conf->intf;
+               for(i=1; i <= conf->bNumInterfaces; i++) {
+                       printf("    === Interface Descriptor %d ===\n", i);
+                       printf("    bLength 0x%02X\n", ifs->bLength);
+                       printf("    bDescriptorType 0x%02X\n", ifs->bDescriptorType);
+                       printf("    bInterfaceNumber 0x%02X\n", ifs->bInterfaceNumber);
+                       printf("    bAlternateSetting 0x%02X\n", ifs->bAlternateSetting);
+                       printf("    bNumEndpoints 0x%02X\n", ifs->bNumEndpoints);
+                       printf("    bInterfaceClass 0x%02X\n", ifs->bInterfaceClass);
+                       printf("    bInterfaceSubClass 0x%02X\n", ifs->bInterfaceSubClass);
+                       printf("    bInterfaceProtocol 0x%02X\n", ifs->bInterfaceProtocol);
+                       printf("    iInterface (0x%02X): \"%s\"\n", ifs->iInterface, ifs->iInterface ? usb_get_string_simple(dev, ifs->iInterface) : "no String");
+
+                       struct usb_endp *ed = ifs->endp;
+                       for(e=1; e <= ifs->bNumEndpoints; e++) {
+                               printf("      === Endpoint Descriptor %d ===\n", e);
+                               printf("      bLength 0x%02X\n", ed->bLength);
+                               printf("      bDescriptorType 0x%02X\n", ed->bDescriptorType);
+                               printf("      bEndpointAddress 0x%02X\n", ed->bEndpointAddress);
+                               printf("      bmAttributes 0x%02X\n", ed->bmAttributes);
+                               printf("      wMaxPacketSize 0x%02X\n", ed->wMaxPacketSize);
+                               printf("      bInterval 0x%02X\n", ed->bInterval);
+
+                               ed = ed->next;
+                       } //endpoint
+
+                       ifs = ifs->next;
+               } //interface
+
+               conf = conf->next;
+       } //configuration
+}
+
+/**
+ * Find currently detached device and remove
+ * data structures
+ */
+u8 usb_remove_device(struct usb_device * dev)
+{
+       // FIXME!!!! dieser quatsch ist nur temporaer
+       free(core.devices->head);
+       free(core.devices);
+       core.devices = list_create();
+       return 1;
+}
+
+/**
+ * Register new driver at usb stack.
+ */
+u8 usb_register_driver(struct usb_driver *dev)
+{
+       /* add driver to driver list */
+       struct element *tmp = (struct element *) malloc(sizeof(struct element));
+       tmp->data = (void *) dev;
+       tmp->next = NULL;
+       list_add_tail(core.drivers, tmp);
+
+       /** 
+        * first check to find a suitable device 
+        * (root hub drivers need this call here)
+        */
+       dev->probe();
+
+       return 1;
+}
+
+
+/**
+ * Call every probe function from every registered
+ * driver, to check if there is a valid driver
+ * for the new device. 
+ */
+void usb_probe_driver()
+{
+       // call ever registered driver  
+       struct usb_driver *drv;
+       struct element *iterator = core.drivers->head;
+       while (iterator != NULL) {
+               drv = (struct usb_driver *) iterator->data;
+               drv->probe();
+               iterator = iterator->next;
+       }
+}
+
+/**
+ * Not implemented.
+ */
+struct usb_irp *usb_get_irp()
+{
+       return 0;
+}
+
+/**
+ * Not implemented.
+ */
+u8 usb_remove_irp(struct usb_irp *irp)
+{
+
+       return 1;
+}
+
+/**
+ * Takes usb_irp and split it into
+ * several usb packeges (SETUP,IN,OUT)
+ * In the usbstack they are transported with the
+ * usb_transfer_descriptor data structure.
+ */
+u16 usb_submit_irp(struct usb_irp *irp)
+{
+       struct usb_transfer_descriptor *td;
+       u8 runloop = 1;
+       u16 restlength = irp->len;
+       u8 *td_buf_ptr = irp->buffer;
+       u8 mybuf[64];
+
+       u8 togl = irp->dev->epTogl[(irp->endpoint & 0x7F)];
+
+       switch (irp->type) {
+       case USB_CTRL:
+               /* alle requests mit dem gleichen algorithmus zerteilen
+                * das einzige ist der spezielle get_Device_descriptor request
+                * bei dem eine laenge von 64 angegeben ist.
+                * wenn man an adresse 0 einen get_device_desciptor schickt
+                * dann reichen die ersten 8 byte.
+                */
+
+               /***************** Setup Stage ***********************/
+               td = usb_create_transfer_descriptor(irp);
+               td->pid = USB_PID_SETUP;
+               td->buffer = irp->buffer;
+
+               /* control message are always 8 bytes */
+               td->actlen = 8;
+
+               togl = 0;
+               /* start with data0 */
+               td->togl = togl;
+               togl = togl ? 0 : 1;
+
+               /**** send token ****/
+               hcdi_enqueue(td, irp->dev->ohci);
+
+               /***************** Data Stage ***********************/
+               /**
+                * You can see at bit 7 of bmRequestType if this stage is used,
+                * default requests are always 8 byte greate, from
+                * host to device. Stage 3 is only neccessary if the request
+                * expected datas from the device.
+                * bit7 - 1 = from device to host -> yes we need data stage
+                * bit7 - 0 = from host to device -> no send zero packet
+                *
+                * nach einem setup token kann nur ein IN token in stage 3 folgen
+                * nie aber ein OUT. Ein Zero OUT wird nur als Bestaetigung benoetigt.
+                *
+                *
+                * bit7 = 1
+                *      Device to Host
+                *      - es kommen noch Daten mit PID_IN an
+                *      - host beendet mit PID_OUT DATA1 Zero
+                * bit7 - 0
+                *      Host zu Device (wie set address)
+                *      - device sendet ein PID_IN DATA1 Zero Packet als bestaetigung
+                */
+               memcpy(mybuf, irp->buffer, td->actlen);
+               usb_device_request *setup = (usb_device_request *) mybuf;
+               u8 bmRequestType = setup->bmRequestType;
+               free(td);
+
+               /* check bit 7 of bmRequestType */
+               if (bmRequestType & 0x80) { 
+                       /* schleife die die tds generiert */
+                       while (runloop && (restlength > 0)) {
+                               td = usb_create_transfer_descriptor(irp);
+                               td->actlen = irp->epsize;
+                               /* stop loop if all bytes are send */
+                               if (restlength < irp->epsize) {
+                                       runloop = 0;
+                                       td->actlen = restlength;
+                               }
+
+                               td->buffer = td_buf_ptr;
+                               /* move pointer for next packet */
+                               td_buf_ptr += irp->epsize;
+
+                               td->pid = USB_PID_IN;
+                               td->togl = togl;
+                               togl = togl ? 0 : 1;
+
+                               /* wenn device descriptor von adresse 0 angefragt wird werden nur
+                                * die ersten 8 byte abgefragt
+                                */
+                               if (setup->bRequest == GET_DESCRIPTOR && (setup->wValue & 0xff) == 1
+                                               && td->devaddress == 0) {
+                                       /* stop loop */
+                                       runloop = 0;
+                               }
+
+                               /**** send token ****/
+                               hcdi_enqueue(td, irp->dev->ohci);
+
+                               /* pruefe ob noch weitere Pakete vom Device abgeholt werden muessen */
+                               restlength = restlength - irp->epsize;
+                               free(td);
+                       }
+               }
+
+
+               /***************** Status Stage ***********************/
+               /* Zero packet for end */
+               td = usb_create_transfer_descriptor(irp);
+               td->togl = 1;                                                           /* zero data packet = always DATA1 packet */
+               td->actlen = 0;
+               td->buffer = NULL;
+
+               /**
+                * bit7 = 1, host beendet mit PID_OUT DATA1 Zero
+                * bit7 = 0, device sendet ein PID_IN DATA1 Zero Packet als bestaetigung
+                */
+               /* check bit 7 of bmRequestType */
+               if (bmRequestType & 0x80) {
+                       td->pid = USB_PID_OUT;
+               } else {
+                       td->pid = USB_PID_IN;
+               }
+               /**** send token ****/
+               hcdi_enqueue(td, irp->dev->ohci);
+               free(td);
+               break;
+
+       case USB_BULK:
+               //u8 runloop=1;
+               //u16 restlength = irp->len;
+               //char * td_buf_ptr=irp->buffer;
+
+               /* schleife die die tds generiert */
+               while (runloop) {
+                       td = usb_create_transfer_descriptor(irp);
+                       td->endpoint = td->endpoint & 0x7F;                             /* clear direction bit */
+
+                       /* max packet size for given endpoint */
+                       td->actlen = irp->epsize;
+
+                       /* Generate In Packet  */
+                       if (irp->endpoint & 0x80)
+                               td->pid = USB_PID_IN;
+                       else
+                               /* Generate Out Packet */
+                               td->pid = USB_PID_OUT;
+
+                       /* stop loop if all bytes are send */
+                       if (restlength <= irp->epsize) {
+                               runloop = 0;
+                               td->actlen = restlength;
+                       }
+
+                       td->buffer = td_buf_ptr;
+                       /* move pointer for next packet */
+                       td_buf_ptr = td_buf_ptr + irp->epsize;
+
+                       td->togl = togl;
+                       togl = togl ? 0 : 1;
+                               /**** send token ****/
+                       hcdi_enqueue(td, irp->dev->ohci);
+                       free(td);
+               }
+               /* next togl */
+               //if(td->pid == USB_PID_OUT) {
+               //if(togl==0) togl=1; else togl=0;
+               //}
+               irp->dev->epTogl[(irp->endpoint & 0x7F)] = togl;
+
+               break;
+       
+       case USB_INTR:
+               //u8 runloop=1;
+               //u16 restlength = irp->len;
+               //char * td_buf_ptr=irp->buffer;
+
+               /* schleife die die tds generiert */
+               while (runloop && (restlength > 0)) {
+                       td = usb_create_transfer_descriptor(irp);
+                       /* max packet size for given endpoint */
+                       td->actlen = irp->epsize;
+
+                       td->pid = USB_PID_IN;
+                       /* TODO: USB_PID_OUT */
+
+                       /* stop loop if all bytes are send */
+                       if (restlength < irp->epsize) {
+                               runloop = 0;
+                               td->actlen = restlength;
+                       }
+
+                       td->buffer = td_buf_ptr;
+                       /* move pointer for next packet */
+                       td_buf_ptr += irp->epsize;
+
+                       td->togl = togl;
+                       togl = togl ? 0 : 1;
+                               
+                       /**** send token ****/
+                       hcdi_enqueue(td, irp->dev->ohci);
+                       restlength = restlength - irp->epsize;
+                       free(td);
+               }
+               break;
+               irp->dev->epTogl[(irp->endpoint & 0x7F)] = togl;
+       }
+       hcdi_fire(irp->dev->ohci);
+
+       return 1;
+}
+
+
+
+/** 
+ * Create a transfer descriptor with an parent irp.
+ */
+struct usb_transfer_descriptor *usb_create_transfer_descriptor(struct usb_irp * irp)
+{
+       struct usb_transfer_descriptor *td =
+                       (struct usb_transfer_descriptor *) malloc(sizeof(struct usb_transfer_descriptor));
+
+       td->devaddress = irp->dev->address;
+       td->endpoint = irp->endpoint;
+       td->iso = 0;
+       td->state = USB_TRANSFER_DESCR_NONE;
+       td->maxp = irp->epsize;
+       td->fullspeed = irp->dev->fullspeed;
+       td->type = irp->type;
+
+       return td;
+}
+
diff --git a/usb/core/core.h b/usb/core/core.h
new file mode 100644 (file)
index 0000000..ce9cecf
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *      * Redistributions of source code must retain the above copyright 
+ *              notice, this list of conditions and the following disclaimer.
+ *      * Redistributions in binary form must reproduce the above 
+ *              copyright notice, this list of conditions and the following 
+ *              disclaimer in the documentation and/or other materials provided 
+ *              with the distribution.
+ *      * Neither the name of the FH Augsburg nor the names of its 
+ *              contributors may be used to endorse or promote products derived 
+ *              from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+       ppcskel - a Free Software replacement for the Nintendo/BroadOn bootloader.
+       plugmii core
+
+Copyright (C) 2009     Bernhard Urban <lewurm@gmx.net>
+Copyright (C) 2009     Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
+
+# This code is licensed to you under the terms of the GNU GPL, version 2;
+# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*/
+
+#ifndef _CORE_H_
+#define _CORE_H_
+
+#include "../../types.h"
+#include "../lib/list.h"
+
+
+#include "../../bootmii_ppc.h"
+inline static void wait_ms(int ms)
+{
+       while(ms--)
+               udelay(1000);
+}
+
+struct usb_device {
+       u8 address;
+       u8 fullspeed;
+       u32 ohci;
+
+       /* device descriptor */
+       u8 bLength;
+       u8 bDescriptorType;
+       u16 bcdUSB;
+       u8 bDeviceClass;
+       u8 bDeviceSubClass;
+       u8 bDeviceProtocoll;
+       u8 bMaxPacketSize0;
+       u16 idVendor;
+       u16 idProduct;
+       u16 bcdDevice;
+       u8 iManufacturer;
+       u8 iProduct;
+       u8 iSerialNumber;
+       u8 bNumConfigurations;
+
+       u8 epSize[16];
+       u8 epTogl[16];
+
+       struct usb_conf *conf;
+       struct usb_device *next;
+};
+
+struct usb_conf {
+       u8 bLength;
+       u8 bDescriptorType;
+       u16 wTotalLength;
+       u8 bNumInterfaces;
+       u8 bConfigurationValue;
+       u8 iConfiguration;
+       u8 bmAttributes;
+       u8 bMaxPower;
+
+       struct usb_conf *next;
+       struct usb_intf *intf;
+};
+
+struct usb_intf {
+       u8 bLength;
+       u8 bDescriptorType;
+       u8 bInterfaceNumber;
+       u8 bAlternateSetting;
+       u8 bNumEndpoints;
+       u8 bInterfaceClass;
+       u8 bInterfaceSubClass;
+       u8 bInterfaceProtocol;
+       u8 iInterface;
+
+       struct usb_intf *next;
+       struct usb_endp *endp;
+};
+
+struct usb_endp {
+       u8 bLength;
+       u8 bDescriptorType;
+       u8 bEndpointAddress;
+       u8 bmAttributes;
+       u16 wMaxPacketSize;
+       u8 bInterval;
+
+       struct usb_endp *next;
+};
+
+struct usb_endpoint {
+       u8 type;
+       u8 size;
+       u8 togl;
+       struct usb_endpoint *next;
+};
+
+struct usb_transfer_descriptor_ep {
+       struct usb_transfer_descriptor_ep *next;
+       u8 device_address;
+       u8 endpoint;
+       struct usb_transfer_descriptor *start;
+};
+
+/**
+ * USB Driver data structure
+ */
+struct usb_driver {
+       char* name;
+       void (*probe)(void);
+       void (*check)(void);
+       void *data;
+       struct usb_driver *next;
+};
+
+
+/**
+ * I/O Request Block
+ */
+
+struct usb_irp {
+       struct usb_device *dev;
+       /* ep -> bit 7 is for direction 1=from  dev to host */
+       u8 endpoint;
+       u8 epsize;
+       /* control, interrupt, bulk or isochron */
+       u8 type;
+
+       u8 *buffer;
+       u16 len;
+
+       //list * td_list;
+       u16 timeout;
+};
+
+
+/**
+ * usb transfer descriptor
+ */
+struct usb_transfer_descriptor {
+       u8 devaddress;
+       u8 endpoint;
+       u8 fullspeed;
+       u8 type;
+       
+       // TODO: zusammenfassen!
+       u8 pid;
+       u8 iso;
+       u8 togl;        
+       
+       u8 *buffer;
+       u16 actlen;
+       
+       u8 state;
+       struct usb_transfer_descriptor *next;
+       u8 maxp;
+};
+
+struct usb_core {
+       u8 nextaddress;
+       void (*stdout)(char * arg); 
+       // driver list
+       struct list *drivers;
+       struct list *devices;
+} core;
+
+void usb_init(u32 reg);
+void usb_periodic();
+u8 usb_next_address();
+
+
+struct usb_device *usb_add_device(u8 lowspeed, u32 reg);
+u8 usb_remove_device(struct usb_device *dev);
+u8 usb_register_driver(struct usb_driver *driver);
+void usb_probe_driver();
+
+void lsusb(struct usb_device *dev);
+
+struct usb_irp *usb_get_irp();
+u8 usb_remove_irp(struct usb_irp *irp);
+u16 usb_submit_irp(struct usb_irp *irp);
+
+
+struct usb_transfer_descriptor *usb_create_transfer_descriptor(struct usb_irp *irp);
+
+
+#define USB_IRP_WAITING                1
+
+
+#define USB_TRANSFER_DESCR_NONE 1
+#define USB_TRANSFER_DESCR_SEND 2
+
+#endif //_CORE_H_
diff --git a/usb/core/usb.c b/usb/core/usb.c
new file mode 100644 (file)
index 0000000..8b766b0
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ * I take the function names and parameters mainly from
+ * libusb.sf.net.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+       ppcskel - a Free Software replacement for the Nintendo/BroadOn bootloader.
+       libusb like interface
+
+Copyright (C) 2009     Bernhard Urban <lewurm@gmx.net>
+Copyright (C) 2009     Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
+
+# This code is licensed to you under the terms of the GNU GPL, version 2;
+# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*/
+
+#include "usb.h"
+#include "core.h"
+#include "../host/host.h"
+#include "../usbspec/usb11spec.h"
+#include "../../malloc.h"
+#include "../../string.h"
+
+#define cleargbuf() memset(gbuf, 0, 0xffff)
+/* internal global buffer */
+static u8 gbuf[0xffff];
+
+/******************* Device Operations **********************/
+/**
+ * Open a device with verndor- and product-id for a communication.
+ */
+struct usb_device *usb_open(u32 vendor_id, u32 product_id)
+{
+       struct usb_device* dev;
+       struct element * iterator = core.devices->head;
+       while(iterator != NULL) {
+               dev = (struct usb_device*)iterator->data;
+               
+               if(dev->idVendor==vendor_id&&dev->idProduct==product_id)
+                       return dev;
+
+               iterator=iterator->next;
+       }
+
+       return NULL;
+}
+
+
+/**
+ * Open a device with an class code for a communication.
+ */
+struct usb_device *usb_open_class(u8 class)
+{
+       struct usb_device* dev;
+       struct element * iterator = core.devices->head;
+       while(iterator != NULL) {
+               dev = (struct usb_device*)iterator->data;
+               
+               if(dev->bDeviceClass==class)
+                       return dev;
+
+               iterator=iterator->next;
+       }
+       return NULL;
+}
+
+/* Close device after a communication.
+ */
+s8 usb_close(struct usb_device *dev)
+{
+
+       return 0;
+}
+
+s8 usb_reset(struct usb_device *dev)
+{
+
+
+       return 0;
+}
+
+
+/******************* Control Transfer **********************/
+/**
+ * Create a control transfer.
+ */
+s8 usb_control_msg(struct usb_device *dev, u8 requesttype, u8 request,
+               u16 value, u16 index, u16 length, u8 *buf, u16 timeout)
+{
+       struct usb_irp *irp = (struct usb_irp*)malloc(sizeof(struct usb_irp));
+       irp->dev = dev;
+       irp->endpoint = 0;
+
+       irp->epsize = dev->bMaxPacketSize0;
+       irp->type = USB_CTRL;
+
+       buf[0]=(u8)requesttype;
+       buf[1]=(u8)request;
+       buf[2]=(u8)(value);
+       buf[3]=(u8)(value >> 8);
+       buf[4]=(u8)(index);
+       buf[5]=(u8)(index >> 8);
+       buf[6]=(u8)(length);
+       buf[7]=(u8)(length >> 8);
+
+       irp->buffer = buf;
+       irp->len = length;
+       irp->timeout = timeout;
+
+       usb_submit_irp(irp);
+       free(irp);
+
+       return 0;
+}
+
+s8 usb_get_descriptor(struct usb_device *dev, u8 type, u8 index, u8 *buf, u8 size)
+{
+       usb_control_msg(dev, 0x80, GET_DESCRIPTOR, (type << 8) | index, 0, size, buf, 0);
+       return 0;
+}
+
+s8 usb_get_string(struct usb_device *dev, u8 index, u8 langid)
+{
+
+       return 0;
+}
+
+char *usb_get_string_simple(struct usb_device *dev, u8 index)
+{
+       cleargbuf();
+       usb_get_descriptor(dev, STRING, index, gbuf, (u8) 8);
+       usb_get_descriptor(dev, STRING, index, gbuf, gbuf[0]);
+
+       char *str = (char*)malloc((gbuf[0]/2));
+       memset(str, '\0', (gbuf[0]/2));
+
+       u16 i;
+       for(i=0; i<(gbuf[0]/2)-1; i++) {
+               str[i] = gbuf[2+(i*2)];
+       }
+
+       return str;
+}
+
+/* ask first 8 bytes of device descriptor with this special 
+ * GET Descriptor Request, when device address = 0
+ */
+s8 usb_get_desc_dev_simple(struct usb_device *dev)
+{
+       cleargbuf();
+       usb_get_descriptor(dev, DEVICE, 0, gbuf, 8);
+
+       if(!gbuf[7]) {
+               printf("FU: %d\n", gbuf[7]);
+               return -2;
+       }
+       dev->bMaxPacketSize0 = gbuf[7];
+       return 0;
+}
+
+s8 usb_get_desc_dev(struct usb_device *dev)
+{
+       cleargbuf();
+       if (usb_get_desc_dev_simple(dev) < 0) {
+               return -1;
+       }
+       usb_get_descriptor(dev, DEVICE, 0, gbuf, gbuf[0]);
+
+       dev->bLength = gbuf[0];
+       dev->bDescriptorType = gbuf[1];
+       dev->bcdUSB = (u16) (gbuf[3] << 8 | gbuf[2]);
+       dev->bDeviceClass = gbuf[4];
+       dev->bDeviceSubClass = gbuf[5];
+       dev->bDeviceProtocoll = gbuf[6];
+       dev->idVendor = (u16) (gbuf[9] << 8) | (gbuf[8]);
+       dev->idProduct = (u16) (gbuf[11] << 8) | (gbuf[10]);
+       dev->bcdDevice = (u16) (gbuf[13] << 8) | (gbuf[12]);
+       dev->iManufacturer = gbuf[14];
+       dev->iProduct = gbuf[15];
+       dev->iSerialNumber = gbuf[16];
+       dev->bNumConfigurations = gbuf[17];
+
+       u8 i;
+       struct usb_conf *conf = dev->conf = (struct usb_conf*) malloc(sizeof(struct usb_conf));
+       for(i=0; i <= dev->bNumConfigurations; i++) {
+               if(i!=0) {
+                       conf = (struct usb_conf*) malloc(sizeof(struct usb_conf));
+               }
+               usb_get_desc_config_ext(dev, i, conf);
+       }
+
+       return 0;
+}
+
+s8 usb_get_desc_configuration(struct usb_device *dev, u8 index, struct usb_conf *conf)
+{
+       cleargbuf();
+       usb_get_descriptor(dev, CONFIGURATION, index, gbuf, 8);
+       usb_get_descriptor(dev, CONFIGURATION, index, gbuf, gbuf[0]);
+
+       conf->bLength = gbuf[0];
+       conf->bDescriptorType = gbuf[1];
+       conf->wTotalLength = (u16) (gbuf[3] << 8 | gbuf[2]);
+       conf->bNumInterfaces = gbuf[4];
+       conf->bConfigurationValue = gbuf[5];
+       conf->iConfiguration = gbuf[6];
+       conf->bmAttributes = gbuf[7];
+       conf->bMaxPower = gbuf[8];
+       conf->intf = NULL;
+
+       return 0;
+}
+
+/* returns more information about CONFIGURATION, including
+ * INTERFACE(s) and ENDPOINT(s)
+ * usb_get_desc_configuration() must be called for this device before
+ */
+s8 usb_get_desc_config_ext(struct usb_device *dev, u8 index, struct usb_conf *conf)
+{
+       cleargbuf();
+
+       usb_get_desc_configuration(dev, index, conf);
+       usb_get_descriptor(dev, CONFIGURATION, index, gbuf, dev->conf->wTotalLength);
+
+       u8 i,j,off=9;
+       struct usb_intf *ifs = dev->conf->intf = (struct usb_intf*) malloc(sizeof(struct usb_intf));
+       for(i=1; i <= dev->conf->bNumInterfaces; i++) {
+               if(i!=1) {
+                       ifs->next = (struct usb_intf*) malloc(sizeof(struct usb_intf));
+                       ifs = ifs->next;
+               }
+               ifs->bLength = gbuf[off+0];
+               ifs->bDescriptorType = gbuf[off+1];
+               ifs->bInterfaceNumber = gbuf[off+2];
+               ifs->bAlternateSetting = gbuf[off+3];
+               ifs->bNumEndpoints = gbuf[off+4];
+               ifs->bInterfaceClass = gbuf[off+5];
+               ifs->bInterfaceSubClass = gbuf[off+6];
+               ifs->bInterfaceProtocol = gbuf[off+7];
+               ifs->iInterface = gbuf[off+8];
+
+               off += 9;
+
+               struct usb_endp *ep = ifs->endp = (struct usb_endp*) malloc(sizeof(struct usb_endp));
+               for(j=1; j <= ifs->bNumEndpoints; j++) {
+                       /* skip HID Device Descriptor (see lsusb) */
+                       if(gbuf[off+1] == 33) {
+                               j--;
+                               off += 9;
+                               continue;
+                       }
+
+                       if(j!=1) {
+                               ep->next = (struct usb_endp*) malloc(sizeof(struct usb_endp));
+                               ep = ep->next;
+                       }
+
+                       ep->bLength = gbuf[off+0];
+                       ep->bDescriptorType = gbuf[off+1];
+                       ep->bEndpointAddress = gbuf[off+2];
+                       ep->bmAttributes = gbuf[off+3];
+                       ep->wMaxPacketSize = (u16) ((gbuf[off+5] << 8) | (gbuf[off+4]));
+                       ep->bInterval = gbuf[off+6];
+
+                       off += 7;
+               }
+       }
+       return 0;
+}
+
+s8 usb_set_address(struct usb_device *dev, u8 address)
+{
+       cleargbuf();
+       usb_control_msg(dev, 0x00, SET_ADDRESS, address, 0, 0, gbuf, 0);
+       hexdump((void*) gbuf, 8);
+       wait_ms(210);
+       return 0;
+}
+
+
+u8 usb_get_configuration(struct usb_device *dev)
+{
+       cleargbuf();
+       usb_control_msg(dev, 0x80, GET_CONFIGURATION, 0, 0, 4, gbuf, 0);
+       printf("=============\nafter usb_get_configuration:\n");
+       hexdump((void*) gbuf, 8);
+       return gbuf[0];
+}
+
+s8 usb_set_configuration(struct usb_device *dev, u8 configuration)
+{
+       cleargbuf();
+       usb_control_msg(dev, 0x00, SET_CONFIGURATION, configuration, 0, 0, gbuf, 0);
+       printf("=============\nafter usb_set_configuration:\n");
+       hexdump((void*) gbuf, 8);
+       wait_ms(20);
+       return 0;
+}
+
+s8 usb_set_altinterface(struct usb_device *dev, u8 alternate)
+{
+
+       return 0;
+}
+
+
+
+/******************* Bulk Transfer **********************/
+/**
+ * Write to an a bulk endpoint.
+ */
+s8 usb_bulk_write(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout)
+{
+       struct usb_irp * irp = (struct usb_irp*)malloc(sizeof(struct usb_irp));
+       irp->dev = dev;
+       //irp->devaddress = dev->address;
+       
+       irp->endpoint = ep;
+       irp->epsize = dev->epSize[ep]; // ermitteln
+       irp->type = USB_BULK;
+
+       irp->buffer = buf;
+       irp->len = size;
+       irp->timeout = timeout;
+
+       usb_submit_irp(irp);
+       free(irp);
+
+       return 0;
+}
+
+/**
+ * Read from an bulk endpoint.
+ */
+s8 usb_bulk_read(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout)
+{
+       struct usb_irp * irp = (struct usb_irp*)malloc(sizeof(struct usb_irp));
+       //irp->devaddress = dev->address;
+       irp->dev = dev;
+       
+       irp->endpoint = ep | 0x80;      // from device to host
+       irp->epsize = dev->epSize[ep]; // ermitteln
+       irp->type = USB_BULK;
+
+       irp->buffer = buf;
+       irp->len = size;
+       irp->timeout = timeout;
+
+       usb_submit_irp(irp);
+       free(irp);
+
+       return 0;
+}
+
+
+/******************* Interrupt Transfer **********************/
+/**
+ * Write to an interrupt endpoint.
+ */
+s8 usb_interrupt_write(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout)
+{
+       return 0;
+}
+
+/**
+ * Read from an interrupt endpoint.
+ */
+s8 usb_interrupt_read(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout)
+{
+       struct usb_irp *irp = (struct usb_irp*)malloc(sizeof(struct usb_irp));
+       irp->dev = dev;
+       irp->endpoint = ep; //wtf? |80; //from device to host
+       irp->epsize = dev->epSize[ep]; // ermitteln
+       irp->type = USB_INTR;
+
+       irp->buffer = buf;
+       irp->len = size;
+       irp->timeout = timeout;
+
+       usb_submit_irp(irp);
+       free(irp);
+
+       return 0;
+}
+
+
+/******************* Isochron Transfer **********************/
+
+/**
+ * Write to an isochron endpoint.
+ */
+s8 usb_isochron_write(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout)
+{
+
+       return 0;
+}
+
+/**
+ * Read from an isochron endpoint.
+ */
+s8 usb_isochron_read(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout)
+{
+
+
+       return 0;
+}
+
+
+//#endif       //_USB_H_
diff --git a/usb/core/usb.h b/usb/core/usb.h
new file mode 100644 (file)
index 0000000..d5cb53b
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2006, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ * I take the function names and parameters mainly from
+ * libusb.sf.net.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+       ppcskel - a Free Software replacement for the Nintendo/BroadOn bootloader.
+       libusb like interface
+
+Copyright (C) 2009     Bernhard Urban <lewurm@gmx.net>
+Copyright (C) 2009     Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
+
+# This code is licensed to you under the terms of the GNU GPL, version 2;
+# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*/
+
+#ifndef _USB_H_
+#define _USB_H_
+
+#include "../../types.h"
+#include "core.h"
+
+
+/******************* Device Operations **********************/
+
+// use an own usb device
+struct usb_device *usb_open(u32 vendor_id, u32 product_id);
+struct usb_device *usb_open_class(u8 class);
+
+s8 usb_close(struct usb_device *dev);
+
+
+/**
+ * usb_reset resets the specified device by sending a RESET down the port 
+ * it is connected to. Returns 0 on success or < 0 on error.
+ */
+
+s8 usb_reset(struct usb_device *dev);
+
+
+/******************* Control Transfer **********************/
+s8 usb_control_msg(struct usb_device *dev, u8 requesttype, u8 request, u16 value, u16 index, u16 length, u8 *buf, u16 timeout);
+s8 usb_get_descriptor(struct usb_device *dev, u8 type, u8 index, u8 *buf, u8 size);
+s8 usb_get_desc_dev_simple(struct usb_device *dev);
+s8 usb_get_desc_dev(struct usb_device *dev);
+s8 usb_get_desc_configuration(struct usb_device *dev, u8 index, struct usb_conf *conf);
+s8 usb_get_desc_config_ext(struct usb_device *dev, u8 index, struct usb_conf *conf);
+
+char *usb_get_string_simple(struct usb_device *dev, u8 index);
+s8 usb_get_string(struct usb_device *dev, u8 index, u8 langid);
+
+s8 usb_set_address(struct usb_device *dev, u8 address);
+u8 usb_get_configuration(struct usb_device *dev);
+s8 usb_set_configuration(struct usb_device *dev, u8 configuration);
+s8 usb_set_altinterface(struct usb_device *dev, u8 alternate);
+
+
+/******************* Bulk Transfer **********************/
+s8 usb_bulk_write(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout);
+s8 usb_bulk_read(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout);
+
+
+/******************* Interrupt Transfer **********************/
+s8 usb_interrupt_write(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout);
+s8 usb_interrupt_read(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout);
+
+
+/******************* Isochron Transfer **********************/
+s8 usb_isochron_write(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout);
+s8 usb_isochron_read(struct usb_device *dev, u8 ep, u8 *buf, u8 size, u8 timeout);
+
+#endif //_USB_H_
diff --git a/usb/drivers/class/hid.c b/usb/drivers/class/hid.c
new file mode 100644 (file)
index 0000000..60d3a4d
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+       ppcskel - a Free Software replacement for the Nintendo/BroadOn bootloader.
+       hid driver
+
+Copyright (C) 2009     Bernhard Urban <lewurm@gmx.net>
+Copyright (C) 2009     Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
+
+# This code is licensed to you under the terms of the GNU GPL, version 2;
+# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*/
+
+#include "../../core/core.h"
+#include "../../core/usb.h"
+#include "../../usbspec/usb11spec.h"
+#include "../../../malloc.h"
+#include "../../../string.h"
+
+#include "hid.h"
+
+struct usb_driver hidkb = {
+       .name     = "hidkb",
+       .probe  = usb_hidkb_probe,
+       .check  = usb_hidkb_check,
+       .data     = NULL
+};
+
+void usb_hidkb_init()
+{
+       usb_register_driver(&hidkb);
+}
+
+void usb_hidkb_probe()
+{
+       struct usb_device *dev;
+       struct element *iterator = core.devices->head;
+       
+       while(iterator != NULL) {
+               dev = (struct usb_device*)iterator->data;
+
+               if(dev->conf->intf->bInterfaceClass == HID_CLASSCODE &&
+                               dev->conf->intf->bInterfaceSubClass == 1 && /* keyboard support boot protocol? */
+                               dev->conf->intf->bInterfaceProtocol == 1) { /* keyboard? */
+                       hidkb.data = (void*) dev;
+               }
+
+               iterator=iterator->next;
+       }
+}
+
+void usb_hidkb_check()
+{
+}
+
+struct kbrep *usb_hidkb_getChars() {
+       struct usb_device *dev = (struct usb_device*) hidkb.data;
+       struct kbrep *ret = (struct kbrep*) malloc(sizeof(struct kbrep));
+
+       memset(ret, 0, 8);
+       s8 epnum = dev->conf->intf->endp->bEndpointAddress & 0xf;
+       (void) usb_interrupt_read(dev, epnum, (u8*) ret, 8, 0);
+       printf("============\nusb_interrupt_read:\n");
+       hexdump((void*)ret, 8);
+
+       return ret;
+}
+
diff --git a/usb/drivers/class/hid.h b/usb/drivers/class/hid.h
new file mode 100644 (file)
index 0000000..e8e88d9
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+       ppcskel - a Free Software replacement for the Nintendo/BroadOn bootloader.
+       hid driver
+
+Copyright (C) 2009     Bernhard Urban <lewurm@gmx.net>
+Copyright (C) 2009     Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
+
+# This code is licensed to you under the terms of the GNU GPL, version 2;
+# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*/
+
+
+#ifndef __HID_H
+#define __HID_H
+
+#define MOD_lctrl (1<<0)
+#define MOD_lshift (1<<1)
+#define MOD_lalt (1<<2)
+#define MOD_lwin (1<<3)
+#define MOD_rctrl (1<<4)
+#define MOD_rshift (1<<5)
+#define MOD_ralt (1<<6)
+#define MOD_rwin (1<<7)
+
+struct kbrep {
+       u8 mod;
+       u8 reserved;
+       u8 keys[6];
+};
+
+void usb_hidkb_probe();
+void usb_hidkb_check();
+void usb_hidkb_init();
+
+struct kbrep *usb_hidkb_getChars();
+
+#endif /* __HID_H */
+
diff --git a/usb/drivers/class/hub.c b/usb/drivers/class/hub.c
new file mode 100644 (file)
index 0000000..f86e516
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//#include <wait.h>
+//#include <stdlib.h>
+
+#include "../../core/core.h"
+#include "../../core/usb.h"
+#include "../../usbspec/usb11spec.h"
+
+
+void usb_hub_probe();
+void usb_hub_check();
+
+
+struct usb_driver hub = {
+       .name     = "hub",
+       .probe  = usb_hub_probe,
+       .check  = usb_hub_check,
+       .data     = NULL
+};
+
+void usb_hub_init()
+{
+       usb_register_driver(&hub);      
+}
+
+
+void usb_hub_probe()
+{
+       // schaue ob aktuell enumeriertes geraet ein hub ist
+       #if DEBUG
+       core.stdout("Probe: Hub\r\n");
+       #endif
+       wait_ms(1000);
+       
+       struct usb_device *dev = usb_open_class(HUB_CLASSCODE);
+       if(dev != NULL){
+               hub.data = (void*)dev;          /* save handle */
+               #if DEBUG
+               core.stdout("Hub: Found Hub Device\r\n");
+               #endif 
+        
+               /* install int in EP */
+
+       }
+
+
+
+}
+
+
+void usb_hub_check()
+{
+       // usb_read_interrupt(handle,1,buf); 
+       // ah neue geraet gefunden
+       // mit request den port geziel reseten, damit device adresse 0 hat
+       // enumeration start
+       // usb_add_device()
+       //
+       //
+       // ah geraet entfernt
+       // usb_remove_device(h1);
+
+}
+
+
+u8 usb_hub_get_hub_descriptor(struct usb_device *dev, char * buf)
+{
+       return 0;  
+}
+
+u8 usb_hub_get_hub_status(struct usb_device *dev, char *buf)
+{
+
+
+       return 0;  
+}
+
+
+u8 usb_hub_get_port_status(struct usb_device *dev, char *buf)
+{
+
+
+       return 0;  
+}
+
+u8 usb_hub_clear_port_feature(struct usb_device *dev)
+{
+
+       return 0;  
+}
+
+u8 usb_hub_set_port_feature(struct usb_device *dev, u8 value)
+{
+
+       return 0;  
+}
+
+u8 usb_hub_clear_hub_feature(struct usb_device *dev)
+{
+
+       return 0;  
+}
+
+u8 usb_hub_set_hub_feature(struct usb_device *dev)
+{
+
+       return 0;  
+}
+
+u8 usb_hub_set_hub_descriptor(struct usb_device *dev)
+{
+
+       return 0;  
+}
+
diff --git a/usb/drivers/class/hub.h b/usb/drivers/class/hub.h
new file mode 100644 (file)
index 0000000..7e157b3
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _HUB_H
+#define _HUB_H
+
+void usb_hub_init();
+void usb_hub_probe();
+
+void usb_hub_check();
+u8 usb_hub_get_hub_descriptor(usb_device *dev, char * buf);
+u8 usb_hub_get_hub_status(usb_device *dev, char *buf);
+u8 usb_hub_get_port_status(usb_device *dev, char *buf);
+u8 usb_hub_clear_port_feature(usb_device *dev);
+u8 usb_hub_set_port_feature(usb_device *dev, u8 value);
+u8 usb_hub_clear_hub_feature(usb_device *dev);
+u8 usb_hub_set_hub_feature(usb_device *dev);
+
+u8 usb_hub_set_hub_descriptor(usb_device *dev);
+#endif /* _HUB_H */
+
diff --git a/usb/drivers/class/storage.c b/usb/drivers/class/storage.c
new file mode 100644 (file)
index 0000000..e0e84fd
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+//#include <wait.h>
+//#include <stdlib.h>
+
+#include "../../core/core.h"
+#include "../../core/usb.h"
+#include "../../usbspec/usb11spec.h"
+#include "../../../malloc.h"
+
+#include "storage.h"
+
+
+#define MAX_DEVICES 2
+
+void usb_storage_probe();
+void usb_storage_check();
+
+struct usb_device *massstorage[MAX_DEVICES];
+u16 sectorsize[MAX_DEVICES];
+u8 massstorage_in_use;
+
+struct usb_driver storage = {
+       .name     = "storage",
+       .probe  = usb_storage_probe,
+       .check  = usb_storage_check,
+       .data     = NULL
+};
+
+void usb_storage_init()
+{
+       massstorage_in_use = 0;
+       usb_register_driver(&storage);  
+}
+
+
+void usb_storage_probe()
+{
+       // schaue ob aktuell enumeriertes geraet ein storage ist
+       #if DEBUG
+       core.stdout("Probe: Storage\r\n");
+       #endif
+       /* read interface descriptor for class code */
+       u8 buf[32];
+       
+       struct usb_device* dev;
+       struct element * iterator = core.devices->head;
+       
+       while(iterator != NULL) {
+               dev = (struct usb_device*)iterator->data;
+
+               /* get interface descriptor */
+               usb_control_msg(dev, 0x80, GET_DESCRIPTOR,2, 0, 32, buf, 0);
+
+               if(buf[14]==MASS_STORAGE_CLASSCODE){
+                       massstorage[massstorage_in_use] = dev;
+                       massstorage_in_use++;
+                       #if DEBUG
+                       core.stdout("Storage: Found Storage Device\r\n");
+                       #endif 
+
+                       /* here is only my lib driver test */
+                       usb_storage_open(0);
+                       usb_storage_inquiry(0);
+                       usb_storage_read_capacity(0);
+
+                       //char * buf = (char*)malloc(512);
+                       //free(buf);
+                       //char buf[512];
+                       //usb_storage_read_sector(0,1,buf);
+
+                       /* end of driver test */
+               }
+
+               iterator=iterator->next;
+       }
+}
+
+
+void usb_storage_check()
+{
+       // wird periodisch augerufen
+       // da ein mass storage aber keinen interrupt oder isochronen endpunkt
+       // hat passiert hier nichts
+}
+
+
+
+u8 usb_storage_inquiry(u8 device)
+{
+       /* send cwb "usbc" */
+       
+       usb_storage_cbw *cbw = (usb_storage_cbw*)malloc(sizeof(usb_storage_cbw));
+       cbw->dCBWSignature= 0x43425355;
+       cbw->dCBWTag=0x826A6008;
+       cbw->dCBWDataTransferLength=0x00000024;
+       cbw->bCWDFlags=0x80;
+       cbw->bCBWLun=0x00;
+       cbw->bCBWCBLength=0x01;
+
+       u8 i;
+       for(i=0;i<16;i++)
+               cbw->CBWCB[i]=0x00;
+
+       cbw->CBWCB[0]=0x12; // 0x12 = INQUIRY
+
+       usb_bulk_write(massstorage[device], 2, (u8*)cbw, 31, 0); 
+       usb_bulk_read(massstorage[device], 1, (u8*)cbw, 36, 0); 
+       usb_bulk_read(massstorage[device], 1, (u8*)cbw, 13, 0); 
+
+       free(cbw);
+
+       return 0;
+}
+
+
+u8 usb_storage_read_capacity(u8 device)
+{
+       /* send cwb "usbc" */
+
+       u8 tmp[8];
+       u8 i;
+       usb_storage_cbw  * cbw = (usb_storage_cbw*)malloc(sizeof(usb_storage_cbw));
+
+       usb_control_msg(massstorage[device], 0x02,1,0, 0x8100, 0,tmp, 0);
+
+       cbw->dCBWSignature= 0x43425355;
+       cbw->dCBWTag=0x826A6008;
+       cbw->dCBWDataTransferLength=0x00000008;
+       cbw->bCWDFlags=0x80;
+       cbw->bCBWLun=0x00;
+       cbw->bCBWCBLength=0x0A;
+
+       for(i=0;i<16;i++)
+               cbw->CBWCB[i]=0x00;
+
+       cbw->CBWCB[0]=0x25; // 0x12 = INQUIRY
+
+       usb_bulk_write(massstorage[device], 2, (u8*)cbw, 31, 0); 
+       usb_bulk_read(massstorage[device], 1, (u8*)cbw, 8, 0); 
+       usb_bulk_read(massstorage[device], 1, (u8*)cbw, 13, 0); 
+
+       free(cbw);
+
+       return 0;
+}
+
+
+u8 usb_storage_read_sector(u8 device, u32 sector, char * buf)
+{
+       /* send cwb "usbc" */
+       u8 tmpbuf[] = {0x55,0x53,0x42,0x43,0x08,
+               0xE0,0x63,0x82,0x00,0x02,
+               0x00,0x00,0x80,0x00,0x0A,
+               0x28,0x00,0x00,0x00,0x00,
+               0x00,0x00,0x00,0x01,0x00,
+               0x00,0x00,0x00,0x00,0x00,
+               0x00,
+               0x00,0x00,0x00,0x00,0x00};
+
+       usb_bulk_write(massstorage[device], 2, tmpbuf, 31, 0);
+       //usb_bulk_read(massstorage[device], 1, buf,64,0);
+       //usb_bulk_read(massstorage[device], 1, buf, 13, 0); 
+
+       
+       return 0;
+}
+
+
+u8 usb_storage_write_sector(u8 device, u32 sector, char * buf)
+{
+
+       return 0;
+}
diff --git a/usb/drivers/class/storage.h b/usb/drivers/class/storage.h
new file mode 100644 (file)
index 0000000..4d216f6
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __STORAGE_H
+#define __STORAGE_H
+void usb_storage_probe();
+void usb_storage_check();
+
+/* CSW Status Definitions */
+#define CSW_CMD_PASSED                  0x00
+#define CSW_CMD_FAILED                  0x01
+#define CSW_PHASE_ERROR                 0x02
+
+
+/* SCSI Commands */
+#define SCSI_TEST_UNIT_READY            0x00
+#define SCSI_REQUEST_SENSE              0x03
+#define SCSI_FORMAT_UNIT                0x04
+#define SCSI_INQUIRY                    0x12
+#define SCSI_MODE_SELECT6               0x15
+#define SCSI_MODE_SENSE6                0x1A
+#define SCSI_START_STOP_UNIT            0x1B
+#define SCSI_MEDIA_REMOVAL              0x1E
+#define SCSI_READ_FORMAT_CAPACITIES     0x23
+#define SCSI_READ_CAPACITY              0x25
+#define SCSI_READ10                     0x28
+#define SCSI_WRITE10                    0x2A
+#define SCSI_VERIFY10                   0x2F
+#define SCSI_MODE_SELECT10              0x55
+#define SCSI_MODE_SENSE10               0x5A
+
+
+typedef struct usb_storage_cbw_t usb_storage_cbw;
+struct usb_storage_cbw_t {
+       u32 dCBWSignature;
+       u32 dCBWTag;
+       u32 dCBWDataTransferLength;
+       u8  bCWDFlags;
+       u8  bCBWLun;
+       u8  bCBWCBLength;
+       u8  CBWCB[16];
+};
+
+typedef struct usb_storage_csw_t usb_storage_csw;
+struct usb_storage_csw_t {
+       u32 dCSWSignature;
+       u32 dCSWTag;
+       u32 dCSWDataResidue;
+       u8  bCSWStatus;
+};
+
+
+void usb_storage_init();
+
+u8 usb_storage_open(u8 device);
+
+u8 usb_storage_read_capacity(u8 device);
+u8 usb_storage_inquiry(u8 device);
+u8 usb_storage_read_sector(u8 device, u32 sector, char * buf);
+u8 usb_storage_write_sector(u8 device, u32 sector, char * buf);
+#endif /* __STORAGE_H */
+
diff --git a/usb/drivers/mon/mon.c b/usb/drivers/mon/mon.c
new file mode 100644 (file)
index 0000000..bd7a324
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2006, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#if USBMON
+
+#include <string.h>
+
+#include "mon.h"
+#include <core/core.h>
+#include <uart.h>
+
+void usb_mon_stdout(void *output)
+{
+  core.stdout = output;
+  usbmon_index=0;
+  usbmon_loop=0;
+}
+
+void usb_mon_stdin(unsigned char input)
+{
+  char send[3]={input,0,0};
+  usbmon_buffer[usbmon_index++]=input;
+  // if enter is pressed
+  if(input==0xD){
+    usbmon_buffer[--usbmon_index]=0;
+    usb_mon_command();
+    usbmon_index=0;
+  } else {
+    core.stdout(send);
+  }
+  if((usbmon_loop==0 && input==0xD)){ 
+    send[0]='\n';
+    send[1]='\r';
+    core.stdout(send);
+    core.stdout("usbmon> ");
+  } 
+
+  if((usbmon_loop==1 && input==0xD)){
+    usbmon_loop=0;
+  }
+}
+
+void usb_mon_command()
+{
+  if(strcmp("list",(char*)usbmon_buffer)==0){
+    core.stdout("\r\nDevice list:\r\n");
+  } else if (strcmp("mon",(char*)usbmon_buffer)==0) {
+    core.stdout("\r\n0:02:Bo 00 93 04");
+    core.stdout("\r\n0:02:Bo 00 93 04");
+    usbmon_loop=1;
+  } else if (strcmp("help",(char*)usbmon_buffer)==0) {
+    usb_mon_usage();
+  } else if (strcmp(".",(char*)usbmon_buffer)==0) {
+    usbmon_loop=0;
+  }
+  else {
+    if(usbmon_index>0)
+      core.stdout("\r\nunkown command (type help)");
+  }
+
+}
+
+void usb_mon_usage()
+{
+  core.stdout("\r\nUsage:\r\n");
+  core.stdout("\tlist\t Print device list\r\n");
+  core.stdout("\tmon\t View online traffic\r\n");
+}
+
+
+
+#endif
diff --git a/usb/drivers/mon/mon.h b/usb/drivers/mon/mon.h
new file mode 100644 (file)
index 0000000..3c7c3dc
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Aufgabefunktion fuer Debugmeldung angeben
+ */
+#if USBMON
+#ifndef _MON_H_
+#define _MON_H_
+
+unsigned char usbmon_buffer[20];
+int usbmon_index;
+int usbmon_loop;
+
+void usb_mon_stdout(void *output);
+void usb_mon_stdin(unsigned char input);
+
+void usb_mon_command();
+void usb_mon_usage();
+
+#endif //_MON_H_
+#endif
diff --git a/usb/drivers/skeleton.c b/usb/drivers/skeleton.c
new file mode 100644 (file)
index 0000000..48b0ec1
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <core/core.h>
+#include <core/usb.h>
+#include <usbspec/usb11spec.h>
+
+#define MAX_DEVICES;
+
+usb_device * devices[MAX_DEVICES];
+u8 devices_in_use;
+
+usb_driver skeleton = {
+       .name    = "skeleton",
+       .probe   = usb_skeleton_probe,
+       .unprobe = usb_skeleton_unprobe,
+       .check   = usb_skeleton_check,
+       .data    = NULL
+};
+
+/* Zum Treiber initialisieren und anmelden am Stack */
+void usb_skeleton_init()
+{
+       devices_in_use = 0;
+       usb_register_driver(&skeleton);
+}
+
+/* Prüfen ob neues Gerät vom Treiber aus angesteuert werden kann */
+void usb_skeleton_probe()
+{
+       usb_device * tmp;
+       tmp = usb_open(0x1234,0x9876);
+       if(tmp!=NULL) {
+               /* neues Gerät gefunden */
+
+               /* wenn Gerät noch nicht in interner Datenstruktur */
+               if(devices_in_use<MAX_DEVICES)
+                       devices[devices_in_use++] = tmp;
+       }
+
+}
+
+/* Entferntes Gerät aus Treiberstrukturen löschen */
+void usb_skeleton_unprobe(usb_device * dev)
+{
+       u8 i;
+       for(i=0;i<MAX_DEVICES;i++) {
+               if(devices[i]==dev)
+                       usb_close(dev);
+       }
+}
+
+/* Für periodische Endpunkte, Verwaltungs- und Steuerungsaufgaben */
+void usb_skeleton_check(){
+
diff --git a/usb/host/host.h b/usb/host/host.h
new file mode 100644 (file)
index 0000000..22e5db7
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2006, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __HOST_H
+#define __HOST_H
+
+#include "../core/core.h"
+
+/**
+ * IRQ from host controller.
+ */
+void hcdi_irq(u32 reg);
+
+
+/**
+ * Intial host controller and necessary software structures.
+ */
+void hcdi_init();
+/**
+ * Enqueue a transfer descriptor.
+ */
+u8 hcdi_enqueue(const struct usb_transfer_descriptor *td, u32 reg);
+/**
+ * Remove an transfer descriptor from transfer queue.
+ */
+u8 hcdi_dequeue(struct usb_transfer_descriptor *td, u32 reg);
+
+void hcdi_fire(u32 reg);
+
+#endif /* __HOST_H */
diff --git a/usb/host/ohci.c b/usb/host/ohci.c
new file mode 100644 (file)
index 0000000..6feff77
--- /dev/null
@@ -0,0 +1,570 @@
+/*
+       ppcskel - a Free Software replacement for the Nintendo/BroadOn bootloader.
+       ohci hardware support
+
+Copyright (C) 2009     Bernhard Urban <lewurm@gmx.net>
+Copyright (C) 2009     Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
+
+# This code is licensed to you under the terms of the GNU GPL, version 2;
+# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*/
+
+#include "../../bootmii_ppc.h"
+#include "../../hollywood.h"
+#include "../../irq.h"
+#include "../../string.h"
+#include "../../malloc.h"
+#include "ohci.h"
+#include "host.h"
+#include "../usbspec/usb11spec.h"
+
+/* activate control_quirk */
+#define _USE_C_Q
+
+/* macro for accessing u32 variables that need to be in little endian byte order;
+ *
+ * whenever you read or write from an u32 field that the ohci host controller
+ * will read or write from too, use this macro for access!
+ */
+#define LE(dword) (u32)( (((dword) & 0xFF000000) >> 24) | \
+                          (((dword) & 0x00FF0000) >> 8)  | \
+                          (((dword) & 0x0000FF00) << 8)  | \
+                          (((dword) & 0x000000FF) << 24) )
+
+static struct general_td *allocate_general_td();
+static void dbg_op_state(u32 reg);
+static void configure_ports(u8 from_init, u32 reg);
+static void setup_port(u32 ohci, u32 reg, u8 from_init);
+
+static struct ohci_hcca hcca_oh0;
+static struct ohci_hcca hcca_oh1;
+
+
+static struct general_td *allocate_general_td()
+{
+       struct general_td *td;
+       td = (struct general_td *)memalign(16, sizeof(struct general_td));
+       memset(td, 0, sizeof(struct general_td));
+       td->flags = LE(0);
+       td->nexttd = LE(0);
+       td->cbp = td->be = LE(0);
+       return td;
+}
+
+
+static void dbg_op_state(u32 reg) 
+{
+       switch (read32(reg+OHCI_HC_CONTROL) & OHCI_CTRL_HCFS) {
+               case OHCI_USB_SUSPEND:
+                       printf("ohci-- OHCI_USB_SUSPEND\n");
+                       break;
+               case OHCI_USB_RESET:
+                       printf("ohci-- OHCI_USB_RESET\n");
+                       break;
+               case OHCI_USB_OPER:
+                       printf("ohci-- OHCI_USB_OPER\n");
+                       break;
+               case OHCI_USB_RESUME:
+                       printf("ohci-- OHCI_USB_RESUME\n");
+                       break;
+       }
+}
+
+#ifdef _DU_OHCI_F_HALT
+static void dbg_td_flag(u32 flag)
+{
+       printf("**************** dbg_td_flag: 0x%08X ***************\n", flag);
+       printf("CC: %X\tshould be 0, see page 32 (ohci spec)\n", (flag>>28)&0xf);
+       printf("EC: %X\tsee page 20 (ohci spec)\n", (flag>>26)&3);
+       printf(" T: %X\n", (flag>>24)&3);
+       printf("DI: %X\n", (flag>>21)&7);
+       printf("DP: %X\n", (flag>>19)&3);
+       printf(" R: %X\n", (flag>>18)&1);
+       printf("********************************************************\n");
+}
+#endif
+
+static void general_td_fill(struct general_td *dest, const struct usb_transfer_descriptor *src)
+{
+       if(src->actlen) {
+               dest->cbp = LE(virt_to_phys(src->buffer));
+               dest->be = LE(LE(dest->cbp) + src->actlen - 1);
+               /* save virtual address here */
+               dest->bufaddr = (u32) src->buffer;
+       }
+       else {
+               dest->cbp = dest->be = LE(0);
+               dest->bufaddr = 0;
+       }
+
+       dest->buflen = src->actlen;
+
+       dest->flags &= LE(~OHCI_TD_DIRECTION_PID_MASK);
+       switch(src->pid) {
+               case USB_PID_SETUP:
+#ifdef _DU_OHCI_Q
+                       printf("pid_setup\n");
+#endif
+                       dest->flags |= LE(OHCI_TD_DIRECTION_PID_SETUP);
+                       dest->flags |= LE(OHCI_TD_TOGGLE_0);
+                       dest->flags |= LE(OHCI_TD_BUFFER_ROUNDING);
+                       break;
+               case USB_PID_OUT:
+#ifdef _DU_OHCI_Q
+                       printf("pid_out\n");
+#endif
+                       dest->flags |= LE(OHCI_TD_DIRECTION_PID_OUT);
+                       dest->flags |= LE(OHCI_TD_BUFFER_ROUNDING);
+
+                       dest->flags |= src->togl ? LE(OHCI_TD_TOGGLE_1) : LE(OHCI_TD_TOGGLE_0);
+                       break;
+               case USB_PID_IN:
+#ifdef _DU_OHCI_Q
+                       printf("pid_in\n");
+#endif
+                       dest->flags |= LE(OHCI_TD_DIRECTION_PID_IN);
+                       if(src->maxp > src->actlen) {
+                               dest->flags |= LE(OHCI_TD_BUFFER_ROUNDING);
+#ifdef _DU_OHCI_Q
+                               printf("round buffer!\n");
+#endif
+                       }
+                       dest->flags |= src->togl ? LE(OHCI_TD_TOGGLE_1) : LE(OHCI_TD_TOGGLE_0);
+                       break;
+       }
+       dest->flags |= LE(OHCI_TD_SET_DELAY_INTERRUPT(7));
+}
+
+#ifdef _DU_OHCI_F_HALT
+static void dump_address(void *addr, u32 size, const char* str)
+{
+       printf("%s hexdump (%d) @ 0x%08X:\n", str, size, addr);
+       hexdump(addr, size);
+}
+#endif
+
+static struct endpoint_descriptor _edhead;
+struct endpoint_descriptor *edhead = 0;
+void hcdi_fire(u32 reg)
+{
+#ifdef _DU_OHCI_F
+       printf("<^>  <^>  <^> hcdi_fire(start)\n");
+#endif
+
+       if(edhead == 0)
+               return;
+
+#ifdef _USE_C_Q
+       /* quirk... 11ms seems to be a minimum :O */
+       udelay(11000);
+#endif
+
+       write32(reg+OHCI_HC_CTRL_HEAD_ED, virt_to_phys(edhead));
+
+       /* sync it all */
+       sync_after_write(edhead, sizeof(struct endpoint_descriptor));
+#ifdef _DU_OHCI_F
+       dump_address(edhead, sizeof(struct endpoint_descriptor), "edhead(before)");
+#endif
+
+       struct general_td *x = phys_to_virt(LE(edhead->headp) & OHCI_ENDPOINT_HEAD_MASK);
+       while(virt_to_phys(x)) {
+               sync_after_write(x, sizeof(struct general_td));
+#ifdef _DU_OHCI_F
+               dump_address(x, sizeof(struct general_td), "x(before)");
+#endif
+
+               if(x->buflen > 0) {
+                       sync_after_write((void*) phys_to_virt(LE(x->cbp)), x->buflen);
+#ifdef _DU_OHCI_F
+                       dump_address((void*) phys_to_virt(LE(x->cbp)), x->buflen, "x->cbp(before)");
+#endif
+               }
+               x = phys_to_virt(LE(x->nexttd));
+       }
+
+       /* trigger control list */
+       set32(reg+OHCI_HC_CONTROL, OHCI_CTRL_CLE);
+       write32(reg+OHCI_HC_COMMAND_STATUS, OHCI_CLF);
+
+       struct general_td *n=0, *prev = 0, *next = 0;
+       /* poll until edhead->headp is null */
+       do {
+               sync_before_read(edhead, sizeof(struct endpoint_descriptor));
+#ifdef _DU_OHCI_F
+               printf("edhead->headp: 0x%08X\n", LE(edhead->headp));
+#endif
+
+               /* if halted, debug output plz. will break the transfer */
+               if((LE(edhead->headp) & OHCI_ENDPOINT_HALTED)) {
+                       n = phys_to_virt(LE(edhead->headp)&~0xf);
+                       prev = phys_to_virt((u32)prev);
+#ifdef _DU_OHCI_F_HALT
+                       printf("halted!\n");
+#endif
+
+                       sync_before_read((void*) n, sizeof(struct general_td));
+#ifdef _DU_OHCI_F_HALT
+                       printf("n: 0x%08X\n", n);
+                       dump_address(n, sizeof(struct general_td), "n(after)");
+#endif
+                       if(n->buflen > 0) {
+                               sync_before_read((void*) n->bufaddr, n->buflen);
+#ifdef _DU_OHCI_F_HALT
+                               dump_address((void*) n->bufaddr, n->buflen, "n->bufaddr(after)");
+#endif
+                       }
+#ifdef _DU_OHCI_F_HALT
+                       dbg_td_flag(LE(n->flags));
+#endif
+
+                       sync_before_read((void*) prev, sizeof(struct general_td));
+#ifdef _DU_OHCI_F_HALT
+                       printf("prev: 0x%08X\n", prev);
+                       dump_address(prev, sizeof(struct general_td), "prev(after)");
+#endif
+                       if(prev->buflen >0) {
+                               sync_before_read((void*) prev->bufaddr, prev->buflen);
+#ifdef _DU_OHCI_F_HALT
+                               dump_address((void*) prev->bufaddr, prev->buflen, "prev->bufaddr(after)");
+#endif
+                       }
+#ifdef _DU_OHCI_F_HALT
+                       dbg_td_flag(LE(prev->flags));
+                       printf("halted end!\n");
+#endif
+                       goto out;
+               }
+               prev = (struct general_td*) (LE(edhead->headp)&~0xf);
+       } while(LE(edhead->headp)&~0xf);
+
+       n = phys_to_virt(read32(reg+OHCI_HC_DONE_HEAD) & ~1);
+#ifdef _DU_OHCI_F
+       printf("hc_done_head: 0x%08X\n", read32(reg+OHCI_HC_DONE_HEAD));
+#endif
+
+       prev = 0; next = 0;
+       /* reverse done queue */
+       while(virt_to_phys(n) && edhead->tdcount) {
+               sync_before_read((void*) n, sizeof(struct general_td));
+#ifdef _DU_OHCI_F
+               printf("n: 0x%08X\n", n);
+               printf("next: 0x%08X\n", next);
+               printf("prev: 0x%08X\n", prev);
+#endif
+
+               next = n;
+               n = (struct general_td*) phys_to_virt(LE(n->nexttd));
+               next->nexttd = (u32) prev;
+               prev = next;
+
+               edhead->tdcount--;
+       }
+
+       n = next;
+       prev = 0;
+       while(virt_to_phys(n)) {
+#ifdef _DU_OHCI_F
+               dump_address(n, sizeof(struct general_td), "n(after)");
+#endif
+               if(n->buflen > 0) {
+                       sync_before_read((void*) n->bufaddr, n->buflen);
+#ifdef _DU_OHCI_F
+                       dump_address((void*) n->bufaddr, n->buflen, "n->bufaddr(after)");
+#endif
+               }
+#ifdef _DU_OHCI_F
+               dbg_td_flag(LE(n->flags));
+#endif
+               prev = n;
+               n = (struct general_td*) n->nexttd;
+               free(prev);
+       }
+
+       if(reg == OHCI0_REG_BASE) {
+               hcca_oh0.done_head = 0;
+               sync_after_write(&hcca_oh0, sizeof(hcca_oh0));
+       } else if (reg == OHCI1_REG_BASE) {
+               hcca_oh1.done_head = 0;
+               sync_after_write(&hcca_oh1, sizeof(hcca_oh1));
+       }
+
+out:
+       write32(reg+OHCI_HC_CONTROL, read32(reg+OHCI_HC_CONTROL)&~OHCI_CTRL_CLE);
+
+       edhead = 0;
+
+#ifdef _DU_OHCI_F
+       printf("<^>  <^>  <^> hcdi_fire(end)\n");
+#endif
+}
+
+/**
+ * Enqueue a transfer descriptor.
+ */
+u8 hcdi_enqueue(const struct usb_transfer_descriptor *td, u32 reg) {
+#ifdef _DU_OHCI_Q
+       printf("*()*()*()*()*()*()*() hcdi_enqueue(start)\n");
+#endif
+       if(!edhead) {
+               edhead = &_edhead;
+               memset(edhead, 0, sizeof(struct endpoint_descriptor));
+               edhead->flags = LE(OHCI_ENDPOINT_GENERAL_FORMAT);
+               edhead->headp = edhead->tailp = edhead->nexted = LE(0);
+               if(td->fullspeed) {
+                       edhead->flags |= LE(OHCI_ENDPOINT_FULL_SPEED);
+               } else {
+                       edhead->flags |= LE(OHCI_ENDPOINT_LOW_SPEED);
+               }
+               edhead->flags |= LE(OHCI_ENDPOINT_SET_DEVICE_ADDRESS(td->devaddress) |
+                               OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(td->endpoint) |
+                               OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(td->maxp));
+               edhead->tdcount = 0;
+       }
+
+       struct general_td *tdhw = allocate_general_td();
+       general_td_fill(tdhw, td);
+       edhead->tdcount ++;
+
+       if(!edhead->headp) {
+               /* first transfer */
+               edhead->headp = LE(virt_to_phys((void*) ((u32)tdhw & OHCI_ENDPOINT_HEAD_MASK)));
+       }
+       else {
+               /* headp in endpoint already exists
+                * => go to list end
+                */
+               struct general_td *n = (struct general_td*) phys_to_virt(LE(edhead->headp) & OHCI_ENDPOINT_HEAD_MASK);
+               while(LE(n->nexttd)) {
+                       n = phys_to_virt(LE(n->nexttd));
+               }
+               n->nexttd = LE(virt_to_phys((void*) ((u32)tdhw & OHCI_ENDPOINT_HEAD_MASK)));
+#ifdef _DU_OHCI_Q
+               printf("n: 0x%08X\n", n);
+               printf("n->nexttd: 0x%08X\n", phys_to_virt(LE(n->nexttd)));
+#endif
+       }
+
+#ifdef _DU_OHCI_Q
+       printf("*()*()*()*()*()*()*() hcdi_enqueue(end)\n");
+#endif
+       return 0;
+}
+
+
+/**
+ * Remove an transfer descriptor from transfer queue.
+ */
+u8 hcdi_dequeue(struct usb_transfer_descriptor *td, u32 reg) {
+       return 0;
+}
+
+void hcdi_init(u32 reg)
+{
+       printf("ohci-- init\n");
+       dbg_op_state(reg);
+
+       /* disable hc interrupts */
+       set32(reg+OHCI_HC_INT_DISABLE, OHCI_INTR_MIE);
+
+       /* save fmInterval and calculate FSMPS */
+#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7))
+#define FI 0x2edf /* 12000 bits per frame (-1) */
+       u32 fmint = read32(reg+OHCI_HC_FM_INTERVAL) & 0x3fff;
+       if(fmint != FI)
+               printf("ohci-- fminterval delta: %d\n", fmint - FI);
+       fmint |= FSMP (fmint) << 16;
+
+       /* enable interrupts of both usb host controllers */
+       set32(EHCI_CTL, EHCI_CTL_OH0INTE | EHCI_CTL_OH1INTE | 0xe0000);
+
+       /* reset HC */
+       write32(reg+OHCI_HC_COMMAND_STATUS, OHCI_HCR);
+
+       /* wait max. 30us */
+       u32 ts = 30;
+       while ((read32(reg+OHCI_HC_COMMAND_STATUS) & OHCI_HCR) != 0) {
+                if(--ts == 0) {
+                       printf("ohci-- FAILED");
+                       return;
+                }
+                udelay(1);
+       }
+
+       /* disable interrupts; 2ms timelimit here! 
+          now we're in the SUSPEND state ... must go OPERATIONAL
+          within 2msec else HC enters RESUME */
+
+       u32 cookie = irq_kill();
+
+       /* Tell the controller where the control and bulk lists are
+        * The lists are empty now. */
+       write32(reg+OHCI_HC_CTRL_HEAD_ED, 0);
+       write32(reg+OHCI_HC_BULK_HEAD_ED, 0);
+
+       /* set hcca adress */
+       if(reg == OHCI0_REG_BASE) {
+               sync_after_write(&hcca_oh0, 256);
+               write32(reg+OHCI_HC_HCCA, virt_to_phys(&hcca_oh0));
+       } else {
+               sync_after_write(&hcca_oh1, 256);
+               write32(reg+OHCI_HC_HCCA, virt_to_phys(&hcca_oh1));
+       }
+
+       /* set periodicstart */
+#define FIT (1<<31)
+       u32 fmInterval = read32(reg+OHCI_HC_FM_INTERVAL) &0x3fff;
+       u32 fit = read32(reg+OHCI_HC_FM_INTERVAL) & FIT;
+
+       write32(reg+OHCI_HC_FM_INTERVAL, fmint | (fit ^ FIT));
+       write32(reg+OHCI_HC_PERIODIC_START, ((9*fmInterval)/10)&0x3fff);
+
+       /* testing bla */
+       if ((read32(reg+OHCI_HC_FM_INTERVAL) & 0x3fff0000) == 0 || !read32(reg+OHCI_HC_PERIODIC_START)) {
+               printf("ohci-- w00t, fail!! see ohci-hcd.c:669\n");
+       }
+       
+       /* start HC operations */
+       write32(reg+OHCI_HC_CONTROL, OHCI_CONTROL_INIT | OHCI_USB_OPER);
+
+       /* wake on ConnectStatusChange, matching external hubs */
+       write32(reg+OHCI_HC_RH_STATUS, /*RH_HS_DRWE |*/ RH_HS_LPSC);
+
+       /* Choose the interrupts we care about now, others later on demand */
+       write32(reg+OHCI_HC_INT_STATUS, ~0);
+       write32(reg+OHCI_HC_INT_ENABLE, OHCI_INTR_INIT);
+
+       //wtf?
+       wait_ms ((read32(reg+OHCI_HC_RH_DESCRIPTOR_A) >> 23) & 0x1fe);
+
+       configure_ports((u8)1, reg);
+       irq_restore(cookie);
+
+       dbg_op_state(reg);
+}
+
+static void configure_ports(u8 from_init, u32 reg)
+{
+#ifdef _DU_OHCI_RH
+       printf("=== Roothub @ %s ===\n", reg == OHCI0_REG_BASE ? "OHCI0" : "OHCI1");
+       printf("OHCI_HC_RH_DESCRIPTOR_A:\t0x%08X\n", read32(reg+OHCI_HC_RH_DESCRIPTOR_A));
+       printf("OHCI_HC_RH_DESCRIPTOR_B:\t0x%08X\n", read32(reg+OHCI_HC_RH_DESCRIPTOR_B));
+       printf("OHCI_HC_RH_STATUS:\t\t0x%08X\n", read32(reg+OHCI_HC_RH_STATUS));
+       printf("OHCI_HC_RH_PORT_STATUS_1:\t0x%08X\n", read32(reg+OHCI_HC_RH_PORT_STATUS_1));
+       printf("OHCI_HC_RH_PORT_STATUS_2:\t0x%08X\n", read32(reg+OHCI_HC_RH_PORT_STATUS_2));
+#endif
+
+       setup_port(reg, reg+OHCI_HC_RH_PORT_STATUS_1, from_init);
+       setup_port(reg, reg+OHCI_HC_RH_PORT_STATUS_2, from_init);
+#ifdef _DU_OHCI_RH
+       printf("configure_ports done\n");
+#endif
+}
+
+static void setup_port(u32 ohci, u32 reg, u8 from_init)
+{
+       u32 port = read32(reg);
+       if((port & RH_PS_CCS) && ((port & RH_PS_CSC) || from_init)) {
+               write32(reg, RH_PS_CSC);
+
+               wait_ms(120);
+
+               /* clear CSC flag, set PES and start port reset (PRS) */
+               write32(reg, RH_PS_PES);
+               while(!(read32(reg) & RH_PS_PES)) {
+#ifdef _DU_OHCI_RH
+                       printf("fu\n");
+#endif
+                       return;
+               }
+
+               write32(reg, RH_PS_PRS);
+
+               /* spin until port reset is complete */
+               while(!(read32(reg) & RH_PS_PRSC)); // hint: it may stuck here
+#ifdef _DU_OHCI_RH
+               printf("loop done\n");
+#endif
+
+               /* returns usb_device struct */
+               (void) usb_add_device((read32(reg) & RH_PS_LSDA) >> 8, ohci);
+       }
+}
+
+void hcdi_irq(u32 reg)
+{
+       /* read interrupt status */
+       u32 flags = read32(reg+OHCI_HC_INT_STATUS);
+
+       /* when all bits are set to 1 some problem occured */
+       if (flags == 0xffffffff) {
+               printf("ohci-- Houston, we have a serious problem! :(\n");
+               return;
+       }
+
+       /* only care about interrupts that are enabled */
+       flags &= read32(reg+OHCI_HC_INT_ENABLE);
+
+       /* nothing to do? */
+       if (flags == 0) {
+               printf("OHCI Interrupt occured: but not for you! WTF?!\n");
+               return;
+       }
+
+       printf("OHCI Interrupt occured: ");
+       /* UnrecoverableError */
+       if (flags & OHCI_INTR_UE) {
+               printf("UnrecoverableError\n");
+               /* TODO: well, I don't know... nothing,
+                *       because it won't happen anyway? ;-) */
+       }
+
+       /* RootHubStatusChange */
+       if (flags & OHCI_INTR_RHSC) {
+               printf("RootHubStatusChange\n");
+               /* TODO: set some next_statechange variable... */
+               configure_ports(0, reg);
+               write32(reg+OHCI_HC_INT_STATUS, OHCI_INTR_RD | OHCI_INTR_RHSC);
+       }
+       /* ResumeDetected */
+       else if (flags & OHCI_INTR_RD) {
+               printf("ResumeDetected\n");
+               write32(reg+OHCI_HC_INT_STATUS, OHCI_INTR_RD);
+               /* TODO: figure out what the linux kernel does here... */
+       }
+
+       /* WritebackDoneHead */
+       if (flags & OHCI_INTR_WDH) {
+               printf("WritebackDoneHead\n");
+               /* basically the linux irq handler reverse TDs to their urbs
+                * and set done_head to null.
+                * since we are polling atm, just should do the latter task.
+                * however, this won't work for now (i don't know why...)
+                * TODO!
+                */
+#if 0
+               sync_before_read(&hcca_oh0, 256);
+               hcca_oh0.done_head = 0;
+               sync_after_write(&hcca_oh0, 256);
+#endif
+       }
+
+       /* TODO: handle any pending URB/ED unlinks... */
+
+#define HC_IS_RUNNING() 1 /* dirty, i know... just a temporary solution */
+       if (HC_IS_RUNNING()) {
+               write32(reg+OHCI_HC_INT_STATUS, flags);
+               write32(reg+OHCI_HC_INT_ENABLE, OHCI_INTR_MIE);
+       }
+}
+
+void show_frame_no(u32 reg)
+{
+       if(reg == OHCI0_REG_BASE) {
+               sync_before_read(&hcca_oh0, 256);
+               printf("***** frame_no: %d *****\n", LE(hcca_oh0.frame_no));
+       } else if (reg == OHCI1_REG_BASE) {
+               sync_before_read(&hcca_oh1, 256);
+               printf("***** frame_no: %d *****\n", LE(hcca_oh1.frame_no));
+       }
+}
diff --git a/usb/host/ohci.h b/usb/host/ohci.h
new file mode 100644 (file)
index 0000000..845cc63
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+       ppcskel - a Free Software replacement for the Nintendo/BroadOn bootloader.
+       ohci hardware support
+
+Copyright (C) 2009     Bernhard Urban <lewurm@gmx.net>
+Copyright (C) 2009     Sebastian Falbesoner <sebastian.falbesoner@gmail.com>
+
+# This code is licensed to you under the terms of the GNU GPL, version 2;
+# see file COPYING or http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
+*/
+
+#ifndef __OHCI_H__
+#define __OHCI_H__
+
+#include "../../types.h"
+
+/* stolen from drivers/usb/host/ohci.h (linux-kernel) :) */
+
+/* OHCI CONTROL AND STATUS REGISTER MASKS */
+
+/*
+ * HcControl (control) register masks
+ */
+#define OHCI_CTRL_CBSR (3 << 0)        /* control/bulk service ratio */
+#define OHCI_CTRL_PLE  (1 << 2)        /* periodic list enable */
+#define OHCI_CTRL_IE   (1 << 3)        /* isochronous enable */
+#define OHCI_CTRL_CLE  (1 << 4)        /* control list enable */
+#define OHCI_CTRL_BLE  (1 << 5)        /* bulk list enable */
+#define OHCI_CTRL_HCFS (3 << 6)        /* host controller functional state */
+#define OHCI_CTRL_IR   (1 << 8)        /* interrupt routing */
+#define OHCI_CTRL_RWC  (1 << 9)        /* remote wakeup connected */
+#define OHCI_CTRL_RWE  (1 << 10)       /* remote wakeup enable */
+
+/* pre-shifted values for HCFS */
+#define OHCI_USB_RESET (0 << 6)
+#define OHCI_USB_RESUME        (1 << 6)
+#define OHCI_USB_OPER  (2 << 6)
+#define OHCI_USB_SUSPEND       (3 << 6)
+
+/*
+ * HcCommandStatus (cmdstatus) register masks
+ */
+#define OHCI_HCR       (1 << 0)        /* host controller reset */
+#define OHCI_CLF       (1 << 1)        /* control list filled */
+#define OHCI_BLF       (1 << 2)        /* bulk list filled */
+#define OHCI_OCR       (1 << 3)        /* ownership change request */
+#define OHCI_SOC       (3 << 16)       /* scheduling overrun count */
+
+/*
+ * masks used with interrupt registers:
+ * HcInterruptStatus (intrstatus)
+ * HcInterruptEnable (intrenable)
+ * HcInterruptDisable (intrdisable)
+ */
+#define OHCI_INTR_SO   (1 << 0)        /* scheduling overrun */
+#define OHCI_INTR_WDH  (1 << 1)        /* writeback of done_head */
+#define OHCI_INTR_SF   (1 << 2)        /* start frame */
+#define OHCI_INTR_RD   (1 << 3)        /* resume detect */
+#define OHCI_INTR_UE   (1 << 4)        /* unrecoverable error */
+#define OHCI_INTR_FNO  (1 << 5)        /* frame number overflow */
+#define OHCI_INTR_RHSC (1 << 6)        /* root hub status change */
+#define OHCI_INTR_OC   (1 << 30)       /* ownership change */
+#define OHCI_INTR_MIE  (1 << 31)       /* master interrupt enable */
+
+/* For initializing controller (mask in an HCFS mode too) */
+#define OHCI_CONTROL_INIT      (3 << 0)
+#define        OHCI_INTR_INIT \
+               (OHCI_INTR_MIE | OHCI_INTR_RHSC | OHCI_INTR_UE)
+
+/* OHCI ROOT HUB REGISTER MASKS */
+
+/* roothub.portstatus [i] bits */
+#define RH_PS_CCS            0x00000001                /* current connect status */
+#define RH_PS_PES            0x00000002                /* port enable status*/
+#define RH_PS_PSS            0x00000004                /* port suspend status */
+#define RH_PS_POCI           0x00000008                /* port over current indicator */
+#define RH_PS_PRS            0x00000010                /* port reset status */
+#define RH_PS_PPS            0x00000100                /* port power status */
+#define RH_PS_LSDA           0x00000200                /* low speed device attached */
+#define RH_PS_CSC            0x00010000                /* connect status change */
+#define RH_PS_PESC           0x00020000                /* port enable status change */
+#define RH_PS_PSSC           0x00040000                /* port suspend status change */
+#define RH_PS_OCIC           0x00080000                /* over current indicator change */
+#define RH_PS_PRSC           0x00100000                /* port reset status change */
+
+/* roothub.status bits */
+#define RH_HS_LPS           0x00000001         /* local power status */
+#define RH_HS_OCI           0x00000002         /* over current indicator */
+#define RH_HS_DRWE          0x00008000         /* device remote wakeup enable */
+#define RH_HS_LPSC          0x00010000         /* local power status change */
+#define RH_HS_OCIC          0x00020000         /* over current indicator change */
+#define RH_HS_CRWE          0x80000000         /* clear remote wakeup enable */
+
+/* roothub.b masks */
+#define RH_B_DR                0x0000ffff              /* device removable flags */
+#define RH_B_PPCM      0xffff0000              /* port power control mask */
+
+/* roothub.a masks */
+#define        RH_A_NDP        (0xff << 0)             /* number of downstream ports */
+#define        RH_A_PSM        (1 << 8)                /* power switching mode */
+#define        RH_A_NPS        (1 << 9)                /* no power switching */
+#define        RH_A_DT         (1 << 10)               /* device type (mbz) */
+#define        RH_A_OCPM       (1 << 11)               /* over current protection mode */
+#define        RH_A_NOCP       (1 << 12)               /* no over current protection */
+#define        RH_A_POTPGT     (0xff << 24)            /* power on to power good time */
+
+struct ohci_hcca {
+#define NUM_INITS 32
+       u32 int_table[NUM_INITS]; /* periodic schedule */
+       /*
+        * OHCI defines u16 frame_no, followed by u16 zero pad.
+        * Since some processors can't do 16 bit bus accesses,
+        * portable access must be a 32 bits wide.
+        */
+       u32 frame_no;                   /* current frame number */
+       u32 done_head;          /* info returned for an interrupt */
+       u8 reserved_for_hc [116];
+       u8 what [4];               /* spec only identifies 252 bytes :) */
+} ALIGNED(256);
+
+struct endpoint_descriptor {
+       /* required by HC */
+       u32 flags;
+       u32 tailp;
+       u32 headp;
+       u32 nexted;
+
+       /* required by software */
+       u32 tdcount;
+} ALIGNED(16);
+
+#define        OHCI_ENDPOINT_ADDRESS_MASK                              0x0000007f
+#define        OHCI_ENDPOINT_GET_DEVICE_ADDRESS(s)             ((s) & 0x7f)
+#define        OHCI_ENDPOINT_SET_DEVICE_ADDRESS(s)             (s)
+#define        OHCI_ENDPOINT_GET_ENDPOINT_NUMBER(s)    (((s) >> 7) & 0xf)
+#define        OHCI_ENDPOINT_SET_ENDPOINT_NUMBER(s)    ((s) << 7)
+#define        OHCI_ENDPOINT_DIRECTION_MASK                    0x00001800
+#define        OHCI_ENDPOINT_DIRECTION_DESCRIPTOR              0x00000000
+#define        OHCI_ENDPOINT_DIRECTION_OUT                             0x00000800
+#define        OHCI_ENDPOINT_DIRECTION_IN                              0x00001000
+#define        OHCI_ENDPOINT_LOW_SPEED                                 0x00002000
+#define        OHCI_ENDPOINT_FULL_SPEED                                0x00000000
+#define        OHCI_ENDPOINT_SKIP                                              0x00004000
+#define        OHCI_ENDPOINT_GENERAL_FORMAT                    0x00000000
+#define        OHCI_ENDPOINT_ISOCHRONOUS_FORMAT                0x00008000
+#define        OHCI_ENDPOINT_MAX_PACKET_SIZE_MASK              (0x7ff << 16)
+#define        OHCI_ENDPOINT_GET_MAX_PACKET_SIZE(s)    (((s) >> 16) & 0x07ff)
+#define        OHCI_ENDPOINT_SET_MAX_PACKET_SIZE(s)    ((s) << 16)
+#define        OHCI_ENDPOINT_HALTED                                    0x00000001
+#define        OHCI_ENDPOINT_TOGGLE_CARRY                              0x00000002
+#define        OHCI_ENDPOINT_HEAD_MASK                                 0xfffffffc
+
+
+struct general_td {
+       /* required by HC */
+       u32 flags;
+       u32 cbp;
+       u32 nexttd;
+       u32 be;
+
+       /* required by software */
+       u32 bufaddr;
+       u32 buflen;
+       u32 pad1;
+       u32 pad2;
+} ALIGNED(16);
+
+#define        OHCI_TD_BUFFER_ROUNDING                 0x00040000
+#define        OHCI_TD_DIRECTION_PID_MASK              0x00180000
+#define        OHCI_TD_DIRECTION_PID_SETUP             0x00000000
+#define        OHCI_TD_DIRECTION_PID_OUT               0x00080000
+#define        OHCI_TD_DIRECTION_PID_IN                0x00100000
+#define        OHCI_TD_GET_DELAY_INTERRUPT(x)  (((x) >> 21) & 7)
+#define        OHCI_TD_SET_DELAY_INTERRUPT(x)  ((x) << 21)
+#define        OHCI_TD_INTERRUPT_MASK                  0x00e00000
+#define        OHCI_TD_TOGGLE_CARRY                    0x00000000
+#define        OHCI_TD_TOGGLE_0                                0x02000000
+#define        OHCI_TD_TOGGLE_1                                0x03000000
+#define        OHCI_TD_TOGGLE_MASK                             0x03000000
+#define        OHCI_TD_GET_ERROR_COUNT(x)              (((x) >> 26) & 3)
+#define        OHCI_TD_GET_CONDITION_CODE(x)   ((x) >> 28)
+#define        OHCI_TD_SET_CONDITION_CODE(x)   ((x) << 28)
+#define        OHCI_TD_CONDITION_CODE_MASK             0xf0000000
+
+#define OHCI_TD_INTERRUPT_IMMEDIATE                    0x00
+#define OHCI_TD_INTERRUPT_NONE                         0x07
+
+#define OHCI_TD_CONDITION_NO_ERROR                     0x00
+#define OHCI_TD_CONDITION_CRC_ERROR                    0x01
+#define OHCI_TD_CONDITION_BIT_STUFFING         0x02
+#define OHCI_TD_CONDITION_TOGGLE_MISMATCH      0x03
+#define OHCI_TD_CONDITION_STALL                                0x04
+#define OHCI_TD_CONDITION_NO_RESPONSE          0x05
+#define OHCI_TD_CONDITION_PID_CHECK_FAILURE    0x06
+#define OHCI_TD_CONDITION_UNEXPECTED_PID       0x07
+#define OHCI_TD_CONDITION_DATA_OVERRUN         0x08
+#define OHCI_TD_CONDITION_DATA_UNDERRUN                0x09
+#define OHCI_TD_CONDITION_BUFFER_OVERRUN       0x0c
+#define OHCI_TD_CONDITION_BUFFER_UNDERRUN      0x0d
+#define OHCI_TD_CONDITION_NOT_ACCESSED         0x0f
+
+#endif
+
diff --git a/usb/lib/list.c b/usb/lib/list.c
new file mode 100644 (file)
index 0000000..39c9439
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+//#include <stdlib.h>
+#include "list.h"
+#include "../../malloc.h"
+
+struct list* list_create()
+{
+       struct list *l = (struct list*)malloc(sizeof(struct list));
+       l->head = NULL;
+       return l;
+}
+
+u8 list_add_tail(struct list *l, struct element *e)
+{
+       e->next = NULL;
+
+       /* if head is empty put first element here */
+       if(l->head==NULL){
+               l->head = e;
+               return 1;
+       }
+
+       /* find last element */
+       struct element * iterator = l->head;
+
+       while(iterator->next!=NULL) {
+               iterator = iterator->next;
+       } 
+       iterator->next = e;
+
+       return 1;
+}
+
+
+
+// FIXME: untested and unused!! 
+u8 list_delete_element(struct list *l, struct element *e)
+{
+       return 1;
+}
+
+// FIXME: untested and unused!! 
+u8 list_is_element_last(struct list *l, struct element *e)
+{
+       if(e->next==NULL)
+               return 1;
+       else
+               return 0;
+}
+
+
+
+// FIXME: untested and unused!! 
+struct element *list_find_next_element(struct list *l, struct element *e)
+{
+       struct element *iterator = l->head;
+
+       while(iterator!=NULL){
+               if(iterator == e)
+                       return iterator->next;
+               iterator = iterator->next;
+       }
+       return NULL;
+}
+
diff --git a/usb/lib/list.h b/usb/lib/list.h
new file mode 100644 (file)
index 0000000..68d8b36
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _LIST_H_
+#define _LIST_H_
+
+#include "../../types.h"
+
+
+struct element {
+       void *data;
+       struct element *next;
+};
+
+
+struct list {
+       struct element *head;
+};
+
+
+struct list *list_create(void);
+
+u8 list_add_tail(struct list *l, struct element *e);
+u8 list_delete_element(struct list *l, struct element *e);
+
+u8 list_is_element_last(struct list *l, struct element *e);
+
+struct element *list_find_next_element(struct list *l, struct element *e);
+
+#endif // _LIST_H_
+
diff --git a/usb/uclibusb/ft232.c b/usb/uclibusb/ft232.c
new file mode 100644 (file)
index 0000000..73380eb
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <lib/types.h>
+
+#include <core/usb.h>
+#include <usbspec/usb11spec.h>
+
+#include "ft232.h"
+
+/** 
+ * Find and open an FT232 on bus.
+ */
+usb_device * usb_ft232_open()
+{
+  usb_device * dev = usb_open(0x0403,0x6001);
+  char tmp[8];
+
+  if(dev!=NULL) {
+    usb_control_msg(dev, 0x00,SET_CONFIGURATION,0x0100, 0, 0,tmp, 8, 0);
+
+    usb_control_msg(dev, 0x40, 0,0, 0,  0,tmp, 8, 0);
+    usb_control_msg(dev, 0x40, 4,8, 0,  0,tmp, 8, 0);
+    usb_control_msg(dev, 0x40, 3,0x4138, 0,  0,tmp, 8, 0);
+    usb_control_msg(dev, 0x40, 1,0x0303, 0,  0,tmp, 8, 0);
+    usb_control_msg(dev, 0x40, 2,0, 0,  0,tmp, 8, 0);
+    usb_control_msg(dev, 0x40, 1,0x0303, 0,  0,tmp, 8, 0);
+  } else {
+    dev = NULL;
+  }
+  return dev;
+}
+
+/**
+ * Close the opened FT232.
+ */
+void usb_ft232_close(usb_device *dev)
+{
+  return;
+}
+
+/**
+ * Send a buffer.
+ */
+u8 usb_ft232_send(usb_device *dev,char *bytes, u8 length)
+{
+  char tmp[8];
+  usb_bulk_write(dev, 2, bytes, length, 0);
+  usb_control_msg(dev, 0x40, 2,0, 0,  0,tmp, 8, 0);
+  usb_control_msg(dev, 0x40, 1,0x0300, 0,  0,tmp, 8, 0);
+  return 1;
+}
+
+/**
+ * Receive some values.
+ */
+u8 usb_ft232_receive(usb_device *dev,char *bytes, u8 length)
+{
+  usb_bulk_read(dev, 1,  bytes, length,0);
+  return 1;
+}
diff --git a/usb/uclibusb/ft232.h b/usb/uclibusb/ft232.h
new file mode 100644 (file)
index 0000000..dfff678
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __FT232_H
+#define __FT232_H
+#include "../../types.h"
+
+usb_device * usb_ft232_open();
+void usb_ft232_close(usb_device *dev);
+u8 usb_ft232_send(usb_device *dev,char *bytes, u8 length);
+u8 usb_ft232_receive(usb_device *dev,char *bytes, u8 length);
+
+#endif /* __FT232_H */
diff --git a/usb/usbspec/request.c b/usb/usbspec/request.c
new file mode 100644 (file)
index 0000000..555fb6e
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2006, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "usb11spec.h"
+#include "request.h"
+
+void request_usb_get_device_descriptor(char *buf, u8 len)
+{
+       //struct usb_device_request * req = (struct usb_device_request*)buf;
+       // 0x80,0x06,0x00,0x01, 0x00,0x00,0x40,0x00
+       buf[0] = 0x80;
+       buf[1] = 0x06;
+       buf[2] = 0x00;
+       buf[3] = 0x01;
+       buf[4] = 0x00;
+       buf[5] = 0x00;
+       buf[6] = len;
+       buf[7] = 0x00;
+       /*
+       req->bmRequestType=0x80;
+       req->bRequest=GET_DESCRIPTOR;
+       req->wValue=DEVICE;
+       req->wIndex=0x0000;
+       req->wLength=len<<8;
+       */
+}
+
+
+void request_usb_set_address(char *buf, u8 addr)
+{
+       buf[0] = 0x00;
+       buf[1] = 0x05;
+       buf[2] = addr;
+       buf[3] = 0x00;
+       buf[4] = 0x00;
+       buf[5] = 0x00;
+       buf[6] = 0x00;
+       buf[7] = 0x00;
+}
+
diff --git a/usb/usbspec/request.h b/usb/usbspec/request.h
new file mode 100644 (file)
index 0000000..c31f6d7
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2006, Benedikt Sauter <sauter@ixbat.de>
+ * All rights reserved.
+ *
+ * Short descripton of file:
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
+ *
+ *   * Redistributions of source code must retain the above copyright 
+ *     notice, this list of conditions and the following disclaimer.
+ *   * Redistributions in binary form must reproduce the above 
+ *     copyright notice, this list of conditions and the following 
+ *     disclaimer in the documentation and/or other materials provided 
+ *     with the distribution.
+ *   * Neither the name of the FH Augsburg nor the names of its 
+ *     contributors may be used to endorse or promote products derived 
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __REQUEST_H
+#define __REQUEST_H
+#include "../../types.h"
+
+void request_usb_get_device_descriptor(char *buf, u8 len);
+
+void request_usb_set_address(char *buf, u8 addr);
+
+#endif /*__REQUEST_H */
diff --git a/usb/usbspec/usb11spec.h b/usb/usbspec/usb11spec.h
new file mode 100644 (file)
index 0000000..ba36df9
--- /dev/null
@@ -0,0 +1,192 @@
+/* usb11spec.h
+* Copyright (C) 2005  Benedikt Sauter
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program 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 this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+#ifndef _USB11PSEC_H
+#define _USB11SPEC_H
+
+/*-------------------------------------------
+ * device descriptor 
+ * ------------------------------------------*/
+struct usb_device_descriptor 
+{
+       unsigned char   bLength;
+       unsigned char   bDescriptorType;
+       unsigned short  bcdUSB;
+       unsigned char   bDeviceClass;
+       unsigned char   bDeviceSubClass;
+       unsigned char   bDeviceProtocol;
+       unsigned char   bMaxPacketSize0;
+       unsigned short  idVendor;
+       unsigned short  idProduct;
+       unsigned short  bcdDevice;
+       unsigned char   iManufacturer;
+       unsigned char   iProduct;
+       unsigned char   iSerialNumber;
+       unsigned char   bNumConfigurations;
+};
+
+/*-------------------------------------------
+ * configuration descriptor 
+ * ------------------------------------------*/
+
+struct usb_configuration_descriptor 
+{
+       unsigned char   bLength;
+       unsigned char   bDescriptorType;
+       unsigned short  wTotalLength;
+       unsigned char   bNumInterfaces;
+       unsigned char   bConfigurationValue;
+       unsigned char   iConfiguration;
+       unsigned char   bmAttributes;
+       unsigned char   MaxPower;
+};
+
+/*-------------------------------------------
+ * interface descriptor 
+ * ------------------------------------------*/
+
+struct usb_interface_descriptor 
+{
+       unsigned char   bLength;
+       unsigned char   bDescriptorType;
+       unsigned char   bInterfaceNumber;
+       unsigned char   bAlternateSetting;
+       unsigned char   bNumEndpoints;
+       unsigned char   bInterfaceClass;
+       unsigned char   bInterfaceSubClass;
+       unsigned char   bInterfaceProtocol;
+       unsigned char   iInterface;
+};
+
+
+/*-------------------------------------------
+ * endpoint descriptor 
+ * ------------------------------------------*/
+struct usb_endpoint_descriptor 
+{
+       unsigned char   bLength;
+       unsigned char   bDescriptorType;
+       unsigned char   bEndpointAddress;
+       unsigned char   bmAttributes;
+       unsigned short  wMaxPacketSize;
+       unsigned char   bIntervall;
+};
+
+
+
+/*-------------------------------------------
+ * string descriptor 
+ * ------------------------------------------*/
+struct usb_string_descriptor 
+{
+       unsigned char   bLength;
+       unsigned char   bDescriptorType;
+       unsigned char*  String;
+};
+
+
+
+
+/*-------------------------------------------
+ * USB Device Request
+ * ------------------------------------------*/
+typedef struct usb_device_request_t usb_device_request;
+struct usb_device_request_t
+{
+       unsigned char bmRequestType;
+       unsigned char bRequest;
+       unsigned short wValue;
+       unsigned short wIndex;  
+       unsigned short wLength;
+};
+
+/*-------------------------------------------
+ * Get Device Descriptor Request
+ * ------------------------------------------*/
+//char GetDeviceDescriptor[] {0x80,GET_DESCRIPTOR, DEVICE,0x00, 0x00,0x00,0x00,0x40};
+//char GetDeviceDescriptor[] {0x80,GET_DESCRIPTOR, DEVICE,0x00, 0x00,0x00,0x00,0x40};
+//char SetAddress[] {0x00,SET_ADDRESS, 0x00, address, 0x00,0x00,0x00,0x40};
+//char SetAddress[] {0x00,SET_ADDRESS, 0x00, 0x00, 0x00,0x00,0x00,0x00};
+
+
+/*------------------------------------------
+ * transfer types 
+ * ------------------------------------------*/
+
+#define USB_CTRL               0x00
+#define USB_ISOC               0x01
+#define USB_BULK               0x02
+#define USB_INTR               0x03
+
+/*-------------------------------------------
+ * device descriptor types 
+ * ------------------------------------------*/
+#define DO_STANDARD   0x00
+#define DO_CLASS      0x20
+#define DO_VENDOR     0x40
+
+/*-------------------------------------------
+ * standard requests for ep0 
+ * ------------------------------------------*/
+
+#define GET_STATUS             0x00 
+#define CLR_FEATURE            0x01
+#define SET_FEATURE            0x03
+#define SET_ADDRESS            0x05
+#define GET_DESCRIPTOR         0x06
+#define SET_DESCRIPTOR         0x07
+#define GET_CONFIGURATION      0x08
+#define SET_CONFIGURATION      0x09
+#define GET_INTERFACE          0x0A
+#define SET_INTERFACE          0x0B
+
+/*-------------------------------------------
+ * descriptor types 
+ * ------------------------------------------*/
+
+#define DEVICE                 0x01
+#define CONFIGURATION          0x02
+#define STRING                 0x03
+#define INTERFACE              0x04
+#define ENDPOINT               0x05
+#define DEVICEQUALIFIER                0x06 // only usb2.0
+#define OTHERSPEEDCONFIGURATION 0x07 // only usb2.0
+
+
+/*-------------------------------------------
+ * pid fields 
+ * ------------------------------------------*/
+
+#define USB_PID_SOF     0x05
+#define USB_PID_SETUP   0x0D
+#define USB_PID_IN      0x09
+#define USB_PID_OUT     0x01
+#define USB_PID_DATA0   0x03
+#define USB_PID_DATA1   0x0B
+#define USB_PID_ACK     0x02
+#define USB_PID_NACK    0x0A
+#define USB_PID_STALL   0x0E
+#define USB_PID_PRE     0x0C
+
+
+#define HID_CLASSCODE  0x03
+#define MASS_STORAGE_CLASSCODE 0x08
+#define HUB_CLASSCODE          0x09
+
+
+
+#endif /* __USB11SPEC_H__ */