git_version.h
*.d
+.deps/*.d
*.bin
*.elf
*.map
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
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
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);
void gecko_init(void);
int printf(const char *fmt, ...);
+void hexdump(void *d, int len);
// Debug: blink the tray led.
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
#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)
#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
--- /dev/null
+/*
+ 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 :/
+}
+
--- /dev/null
+/*
+ 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
+
+
#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"
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();
; // 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;
}
--- /dev/null
+Benedikt Sauter, sauter@ixbat.de
+Bernhard Urban, lewurm@gmx.net
+Sebastian Falbesoner, sebastian.falbesoner@gmail.com
--- /dev/null
+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.
--- /dev/null
+#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
--- /dev/null
+http://wiibrew.org/wiki/Plugmii
--- /dev/null
+USB Subsystem
+
+
+
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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_
--- /dev/null
+/*
+ * 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_
--- /dev/null
+/*
+ * 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_
--- /dev/null
+/*
+ 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;
+}
+
--- /dev/null
+/*
+ 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 */
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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 */
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
+
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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(){
+
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ 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));
+ }
+}
--- /dev/null
+/*
+ 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
+
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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_
+
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/*
+ * 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;
+}
+
--- /dev/null
+/*
+ * 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 */
--- /dev/null
+/* 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__ */