Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

mroib

  • Loading branch information...
commit ca5a23312e90336c0740aea9634d84cb21174555 1 parent 556c094
@comex authored
View
5 config/config.txt
@@ -1,4 +1,9 @@
CONFIG_MIN
+// for mroib
+CONFIG_KERN_OS_MALLOC
+CONFIG_KERN_OS_FREE
+CONFIG_KERN_OS_REALLOC
+CONFIG_IOMALLOCALIGNED
// for sandbox
CONFIG_IS_ARMV7
CONFIG_VN_GETPATH
View
33 config/keyz.txt
@@ -411,22 +411,6 @@ iPad1,1_4.2.1_8C148.iBSS: 619a29ff91bf924bd1edf8efe48d280f5ec85865dd55dfe5f8989a
iPad1,1_4.2.1_8C148.iBoot: 74476c5215f0b1e4204bf2f748b2adc660a7139e9b57a129ac4cfd3ae86476e8 6ae99830ab64997ad7426d3342ba3bec
iPad1,1_4.2.1_8C148.KernelCache: 0173639a2d737a063b25956464f5907abae4e0081e102330206e8636817561d4 ca2d0d625d71d50f32be0e82ab83415f
-iPhone3,1_4.2.1_8C148.fs: b2ee5018ef7d02e45ef67449d9e2ed5f876efae949de64a9a93dbcf7ff9ed84e041e9167
-iPhone3,1_4.2.1_8C148.AppleLogo: 91866d7b929b971c72fa6e90530a5b2a361bed9486f2cb884b632f61253ed204 0dcee7d1b9982793558d588d84c44af0
-iPhone3,1_4.2.1_8C148.BatteryCharging0: 6059d6622dc37946e52d2fe87d64541b2142362a9f33576647d0e4210bd98d1b bf594f1948cfe699ed81978da918c9a2
-iPhone3,1_4.2.1_8C148.BatteryCharging1: e4b8dd16397ce416a6309b594034c8e024c245dcff046014331d71e307047939 55fbd7a9c6b27af1edc3d79a1e4a7a5e
-iPhone3,1_4.2.1_8C148.BatteryFull: 311b3abb89083cd245b2c00bb9207b3fa721435b4f53836a97c38cfde4b20268 6ea98a78db9deca4cc1d37ab2b01bf72
-iPhone3,1_4.2.1_8C148.BatteryLow0: 809a6d52d5ed34d6d35397c1bce23190a09e353418394b33e60b5257de1ee117 411cf59c075aed7412eac6cb209b635f
-iPhone3,1_4.2.1_8C148.BatteryLow1: fdacba0a29f3b650cd135864ee95cb088cb905342912de93fd5a7bf288c99d75 76d3f38f8badef93c8a243f4e96e739e
-iPhone3,1_4.2.1_8C148.DeviceTree: 91fb8c543820ad313578a175d28e74caac973759a766167e423d872dae361ca7 ea8153bd8ef0b7965e1855959f8706ed
-iPhone3,1_4.2.1_8C148.GlyphCharging: 3fa0ae7d2411725bfbffff4e06adcf24373d641703a0cd24d2fa34c64544f90a 604dfca9640b9f800a3b478adbe63aa0
-iPhone3,1_4.2.1_8C148.GlyphPlugin: edc4ee23eff28d4b021e23d986972558bc9d108b7332abff1600e0e01eac23bf 746787d5ea62187e084c2d0c1f9399cc
-iPhone3,1_4.2.1_8C148.iBEC: 9aa1f074b26ae75bd394e7138f1195dc784bd774c81f9cc4d80f9b3eedd60edf 5125bb86e2139b3f4cfb3a470c699df2
-iPhone3,1_4.2.1_8C148.iBoot: 65b69a67acc72771aea43b15b70a566139a42257bdab7659cdab1ab2537713af dadfae4f4967eff4f149b606cbe34060
-iPhone3,1_4.2.1_8C148.iBSS: 32398d3d1328ed3f0e1949446a1357585ae1973b3c8434b83df49ac55cf45d06 45bbf0fa98573425fa21dc6e529eba6b
-iPhone3,1_4.2.1_8C148.KernelCache: 0173639a2d737a063b25956464f5907abae4e0081e102330206e8636817561d4 ca2d0d625d71d50f32be0e82ab83415f
-iPhone3,1_4.2.1_8C148.LLB: 3c135743c32306664125a9e07cc280ee8fd014830353e385fb13a85b28698d05 e0514f26e05ab9db509033f36d7440e8
-iPhone3,1_4.2.1_8C148.RecoveryMode: ff278adcb52647785fd58ad689739fdcdace7acd08d932b4c32d54ea2c2032d8 9a59ae16a84808e8d7546269e36a21c0
iPod4,1_4.2.1_8C148.fs: 982437b30d334c744c94b9a73ab70e0fc6ed94c181b2a8b0fde6ee03f2546cc9b2c5b01c
iPod4,1_4.2.1_8C148.AppleLogo: 91866d7b929b971c72fa6e90530a5b2a361bed9486f2cb884b632f61253ed204 0dcee7d1b9982793558d588d84c44af0
iPod4,1_4.2.1_8C148.BatteryCharging0: 6059d6622dc37946e52d2fe87d64541b2142362a9f33576647d0e4210bd98d1b bf594f1948cfe699ed81978da918c9a2
@@ -474,3 +458,20 @@ iPhone1,2_4.2.1_8C148.KernelCache: 899504f05b254e543d98fcff61d1dc03 63e4f6107e33
iPhone1,2_4.2.1_8C148.RecoveryMode: 6f12794e39135f36f4edf8b11194b783 e26f281077fcbd85af323327258c1a3c
iPhone1,2_4.2.1_8C148.fs: 82c9280927224637c77a96a26d22f42f2ca08fa9a798a8d06fbc8202fc83ec7f45dda79e
+iPhone3,1_4.2.1_8C148.fs: b2ee5018ef7d02e45ef67449d9e2ed5f876efae949de64a9a93dbcf7ff9ed84e041e9167
+iPhone3,1_4.2.1_8C148.AppleLogo: 91866d7b929b971c72fa6e90530a5b2a361bed9486f2cb884b632f61253ed204 0dcee7d1b9982793558d588d84c44af0
+iPhone3,1_4.2.1_8C148.BatteryCharging0: 6059d6622dc37946e52d2fe87d64541b2142362a9f33576647d0e4210bd98d1b bf594f1948cfe699ed81978da918c9a2
+iPhone3,1_4.2.1_8C148.BatteryCharging1: e4b8dd16397ce416a6309b594034c8e024c245dcff046014331d71e307047939 55fbd7a9c6b27af1edc3d79a1e4a7a5e
+iPhone3,1_4.2.1_8C148.BatteryFull: 311b3abb89083cd245b2c00bb9207b3fa721435b4f53836a97c38cfde4b20268 6ea98a78db9deca4cc1d37ab2b01bf72
+iPhone3,1_4.2.1_8C148.BatteryLow0: 809a6d52d5ed34d6d35397c1bce23190a09e353418394b33e60b5257de1ee117 411cf59c075aed7412eac6cb209b635f
+iPhone3,1_4.2.1_8C148.BatteryLow1: fdacba0a29f3b650cd135864ee95cb088cb905342912de93fd5a7bf288c99d75 76d3f38f8badef93c8a243f4e96e739e
+iPhone3,1_4.2.1_8C148.DeviceTree: 91fb8c543820ad313578a175d28e74caac973759a766167e423d872dae361ca7 ea8153bd8ef0b7965e1855959f8706ed
+iPhone3,1_4.2.1_8C148.GlyphCharging: 3fa0ae7d2411725bfbffff4e06adcf24373d641703a0cd24d2fa34c64544f90a 604dfca9640b9f800a3b478adbe63aa0
+iPhone3,1_4.2.1_8C148.GlyphPlugin: edc4ee23eff28d4b021e23d986972558bc9d108b7332abff1600e0e01eac23bf 746787d5ea62187e084c2d0c1f9399cc
+iPhone3,1_4.2.1_8C148.iBEC: 9aa1f074b26ae75bd394e7138f1195dc784bd774c81f9cc4d80f9b3eedd60edf 5125bb86e2139b3f4cfb3a470c699df2
+iPhone3,1_4.2.1_8C148.iBoot: 65b69a67acc72771aea43b15b70a566139a42257bdab7659cdab1ab2537713af dadfae4f4967eff4f149b606cbe34060
+iPhone3,1_4.2.1_8C148.iBSS: 32398d3d1328ed3f0e1949446a1357585ae1973b3c8434b83df49ac55cf45d06 45bbf0fa98573425fa21dc6e529eba6b
+iPhone3,1_4.2.1_8C148.KernelCache: 9c32276861ad6935b5ed0af954de8953d569492b14be3600fa5fe93d4b8210e3 318e0d3de933babc06d6500d9a6af759
+iPhone3,1_4.2.1_8C148.LLB: 3c135743c32306664125a9e07cc280ee8fd014830353e385fb13a85b28698d05 e0514f26e05ab9db509033f36d7440e8
+iPhone3,1_4.2.1_8C148.RecoveryMode: ff278adcb52647785fd58ad689739fdcdace7acd08d932b4c32d54ea2c2032d8 9a59ae16a84808e8d7546269e36a21c0
+
View
5 make.py
@@ -128,6 +128,11 @@ def nullfs():
goto('nullfs')
run(GCC, '-dynamiclib', '-o', 'nullfs.dylib', 'null_subr.c', 'null_vfsops.c', 'null_vnops.c', 'vfs_pasta.c', '-fwhole-program', '-combine', '-nostdinc', '-nodefaultlibs', '-lgcc', '-Wno-error', '-Wno-parentheses', '-Wno-format', '-I.', '-Ixnu', '-Ixnu/bsd', '-Ixnu/libkern', '-Ixnu/osfmk', '-Ixnu/bsd/i386', '-Ixnu/bsd/sys', '-Ixnu/EXTERNAL_HEADERS', '-Ixnu/osfmk/libsa', '-D__i386__', '-DKERNEL', '-DKERNEL_PRIVATE', '-DBSD_KERNEL_PRIVATE', '-D__APPLE_API_PRIVATE', '-DXNU_KERNEL_PRIVATE', '-flat_namespace', '-undefined', 'dynamic_lookup', '-fno-builtin-printf', '-DNULLFS_DIAGNOSTIC')
+def mroib():
+ goto('mroib')
+ run(GCC, '-c', '-o', 'clean.o', 'clean.c', '-marm')
+ run(GCC, '-dynamiclib', '-o', 'mroib.dylib', 'power.c', 'timer.c', 'usb.c', 'mroib.c', 'clean.o', '-combine', '-fwhole-program', '-nostdinc', '-nodefaultlibs', '-lgcc', '-undefined', 'dynamic_lookup', '-I.', '-Iincludes', '-DCONFIG_IPHONE_4G')
+
def clean():
autoclean()
View
BIN  mroib/.usb.c.swo
Binary file not shown
View
8 mroib/clean.c
@@ -0,0 +1,8 @@
+void CleanAndInvalidateCPUDataCache(void *buffer, int bufferLen) {
+ char *p = buffer;
+ while(bufferLen) {
+ asm("mcr p15, 0, %0, c7, c10, 1" :: "r"(p));
+ p += 0x10; // should be higher
+ bufferLen -= 0x10;
+ }
+}
View
23 mroib/includes/hardware/clock0.h
@@ -0,0 +1,23 @@
+#ifndef HW_CLOCK0_H
+#define HW_CLOCK0_H
+
+#include "hardware/s5l8900.h"
+
+#define CLOCK0 0x38100000 /* the clocks are probably also parts of the system controller */
+
+// Registers
+#define CLOCK0_CONFIG 0x0
+#define CLOCK0_ADJ1 0x8
+#define CLOCK0_ADJ2 0x404
+
+// Values
+#define CLOCK0_ADJ_MASK 0xFFFFF000
+
+#define CLOCK0_CONFIG_BOTTOMMASK 0x7
+#define CLOCK0_CONFIG_C0VALUE 0x1
+#define CLOCK0_CONFIG_C1VALUE 0x3
+#define CLOCK0_CONFIG_C2VALUE 0x5
+#define CLOCK0_CONFIG_C3VALUE 0
+
+#endif
+
View
75 mroib/includes/hardware/clock1.h
@@ -0,0 +1,75 @@
+#ifndef HW_CLOCK1_H
+#define HW_CLOCK1_H
+
+#include "hardware/s5l8900.h"
+
+// Constants
+#define NUM_PLL 4
+#define FREQUENCY_BASE 12000000
+#define PLL0_INFREQ_DIV FREQUENCY_BASE /* 12 MHz */
+#define PLL1_INFREQ_DIV FREQUENCY_BASE /* 12 MHz */
+#define PLL2_INFREQ_DIV FREQUENCY_BASE /* 12 MHz */
+#define PLL3_INFREQ_DIV 13500000 /* 13.5 MHz */
+#define PLL0_INFREQ_MULT 0x4000
+#define PLL1_INFREQ_MULT 0x4000
+#define PLL2_INFREQ_MULT 0x4000
+#define PLL3_INFREQ_MULT FREQUENCY_BASE
+
+// Devices
+#define CLOCK1 0x3C500000
+
+// Registers
+#define CLOCK1_CONFIG0 0x0
+#define CLOCK1_CONFIG1 0x4
+#define CLOCK1_CONFIG2 0x8
+#define CLOCK1_PLL0CON 0x20
+#define CLOCK1_PLL1CON 0x24
+#define CLOCK1_PLL2CON 0x28
+#define CLOCK1_PLL3CON 0x2C
+#define CLOCK1_PLL0LCNT 0x30
+#define CLOCK1_PLL1LCNT 0x34
+#define CLOCK1_PLL2LCNT 0x38
+#define CLOCK1_PLL3LCNT 0x3C
+#define CLOCK1_PLLLOCK 0x40
+#define CLOCK1_PLLMODE 0x44
+#define CLOCK1_CL2_GATES 0x48
+#define CLOCK1_CL3_GATES 0x4C
+
+// Values
+#define CLOCK1_Separator 0x20
+
+#define CLOCK1_CLOCKPLL(x) GET_BITS((x), 12, 2)
+#define CLOCK1_CLOCKDIVIDER(x) (GET_BITS((x), 0, 4) + 1)
+#define CLOCK1_CLOCKHASDIVIDER(x) GET_BITS((x), 8, 1)
+
+#define CLOCK1_MEMORYPLL(x) GET_BITS((x), 12, 2)
+#define CLOCK1_MEMORYDIVIDER(x) (GET_BITS((x), 16, 4) + 1)
+#define CLOCK1_MEMORYHASDIVIDER(x) GET_BITS((x), 24, 1)
+
+#define CLOCK1_BUSPLL(x) GET_BITS((x), 12, 2)
+#define CLOCK1_BUSDIVIDER(x) (GET_BITS((x), 16, 4) + 1)
+#define CLOCK1_BUSHASDIVIDER(x) GET_BITS((x), 24, 1)
+
+#define CLOCK1_UNKNOWNPLL(x) GET_BITS((x), 12, 2)
+#define CLOCK1_UNKNOWNDIVIDER1(x) (GET_BITS((x), 0, 4) + 1)
+#define CLOCK1_UNKNOWNDIVIDER2(x) (GET_BITS((x), 4, 4) + 1)
+#define CLOCK1_UNKNOWNDIVIDER(x) (CLOCK1_UNKNOWNDIVIDER1(x) * CLOCK1_UNKNOWNDIVIDER2(x))
+#define CLOCK1_UNKNOWNHASDIVIDER(x) GET_BITS((x), 8, 1)
+
+#define CLOCK1_PERIPHERALDIVIDER(x) GET_BITS((x), 20, 2)
+
+#define CLOCK1_DISPLAYPLL(x) GET_BITS((x), 28, 2)
+#define CLOCK1_DISPLAYDIVIDER(x) GET_BITS((x), 16, 4)
+#define CLOCK1_DISPLAYHASDIVIDER(x) GET_BITS((x), 24, 1)
+
+#define CLOCK1_PLLMODE_ONOFF(x, y) (((x) >> (y)) & 0x1)
+#define CLOCK1_PLLMODE_DIVIDERMODE(x, y) (((x) >> (y + 4)) & 0x1)
+#define CLOCK1_PLLMODE_DIVIDE 1
+#define CLOCK1_PLLMODE_MULTIPLY 0
+
+#define CLOCK1_MDIV(x) (((x) >> 8) & 0x3FF)
+#define CLOCK1_PDIV(x) (((x) >> 24) & 0x3F)
+#define CLOCK1_SDIV(x) ((x) & 0x3)
+
+#endif
+
View
30 mroib/includes/hardware/clockS5L8730.h
@@ -0,0 +1,30 @@
+#ifndef HW_CLOCKS5L8730_H
+#define HW_CLOCKS5L8730_H
+
+// Clock constants for the S5L8730. This device does not have a distinction
+// between clock0 and clock1 like the S5L8900 does.
+
+#include "hardware/s5l8900.h"
+
+/*
+typedef struct {
+ uint32_t address;
+ uint32_t unkn1;
+ uint8_t unkn_bytes[4];
+} ClockStruct;
+
+typedef struct {
+ uint32_t unkn1;
+ uint8_t unkn2;
+} ClockThirdStruct;
+
+#define CLOCK_REFERENCE_0_FREQUENCY 0x16E3600
+#define CLOCK_REFERENCE_1 0xBF100000
+#define CLOCK_REFERENCE_2 0xBF100008
+#define CLOCK_REFERENCE_3 0xBF100010
+#define CLOCK_REFERENCE_4 0xBF100020
+
+#define CLOCK_ACTIVE(x) GET_BITS(x, 31, 1)
+*/
+
+#endif
View
20 mroib/includes/hardware/edgeic.h
@@ -0,0 +1,20 @@
+#ifndef HW_EDGEIC_H
+#define HW_EDGEIC_H
+
+#include "hardware/s5l8900.h"
+
+// Devices
+#define EDGEIC 0x38E02000
+
+// Registers
+#define EDGEICCONFIG0 0x0
+#define EDGEICCONFIG1 0x4
+#define EDGEICLOWSTATUS 0x8
+#define EDGEICHIGHSTATUS 0xC
+
+// Values
+#define EDGEIC_CONFIG0RESET 0
+#define EDGEIC_CONFIG1RESET 0
+
+#endif
+
View
45 mroib/includes/hardware/interrupt.h
@@ -0,0 +1,45 @@
+#ifndef HW_INTERRUPT_H
+#define HW_INTERRUPT_H
+
+#include "hardware/s5l8900.h"
+
+// This appears to be a PL192
+
+// Constants
+
+#ifndef CONFIG_IPHONE_4G
+#define VIC_MaxInterrupt 0x40
+#else
+#define VIC_MaxInterrupt 0x80
+#endif
+#define VIC_InterruptSeparator 0x20
+
+// Devices
+
+#ifndef CONFIG_IPHONE_4G
+#define VIC0 0x38E00000
+#define VIC1 0x38E01000
+#else
+#define VIC0 0xBF200000
+#define VIC1 0xBF210000
+#define VIC2 0xBF220000
+#define VIC3 0xBF230000
+#endif
+
+// Registers
+
+#define VICIRQSTATUS 0x000
+#define VICRAWINTR 0x8
+#define VICINTSELECT 0xC
+#define VICINTENABLE 0x10
+#define VICINTENCLEAR 0x14
+#define VICSWPRIORITYMASK 0x24
+#define VICVECTADDRS 0x100
+#define VICADDRESS 0xF00
+#define VICPERIPHID0 0xFE0
+#define VICPERIPHID1 0xFE4
+#define VICPERIPHID2 0xFE8
+#define VICPERIPHID3 0xFEC
+
+#endif
+
View
43 mroib/includes/hardware/power.h
@@ -0,0 +1,43 @@
+#ifndef HW_POWER_H
+#define HW_POWER_H
+
+#include "hardware/s5l8900.h"
+
+// Device
+#ifndef CONFIG_IPHONE_4G
+#define POWER 0x39A00000 /* probably a part of the system controller */
+#else
+#define POWER 0xBF100000
+#endif
+
+// Power
+#define POWER_DEFAULT_DEVICES 0xEC
+#define POWER_LCD 0x100
+#define POWER_USB 0x200
+#define POWER_VROM 0x1000
+
+// Registers
+#define POWER_CONFIG0 0x0
+#define POWER_CONFIG1 0x20
+#define POWER_CONFIG2 0x6C
+#define POWER_ONCTRL 0xC
+#define POWER_OFFCTRL 0x10
+#define POWER_SETSTATE 0x8
+#ifndef CONFIG_IPHONE_4G
+#define POWER_STATE 0x14
+#define POWER_ID 0x44
+#else
+#define POWER_STATE 0x1010
+#define POWER_STATE_MAX 0x3F
+#define POWER_ID 0x6000
+#endif
+#define POWER_ID_EPOCH(x) ((x) >> 24)
+
+// Values
+#define POWER_CONFIG0_RESET 0x1123009
+#define POWER_CONFIG1_RESET 0x20
+#define POWER_CONFIG2_RESET 0x0
+
+
+#endif
+
View
82 mroib/includes/hardware/s5l8900.h
@@ -0,0 +1,82 @@
+#ifndef S5L8900_H
+#define S5L8900_H
+
+#include "hardware/s5l8900.h"
+
+/*
+ * Constants
+ */
+
+#define MemoryStart 0x00000000
+#define MemoryEnd 0xFFFFFFFF
+#ifndef CONFIG_IPHONE_4G
+#define LargeMemoryStart 0x08000000 /* FIXME: This is an ugly hack to get around iBoot's memory rearrangement. Linux boot will only work for installed openiboot! */
+#define RAMEnd 0x08000000
+#define MemoryHigher 0x80000000
+#else
+#define LargeMemoryStart 0x60000000
+#define RAMStart 0x40000000
+#define RAMEnd 0x60000000
+#define MemoryHigher 0xC0000000
+#endif
+#define ExceptionVector MemoryStart
+#ifdef SMALL
+#define PageTable (OpenIBootLoad + 0x24000)
+#define HeapStart (PageTable + 0x4000)
+#else
+#define OpenIBootLoad 0x00000000
+#ifndef CONFIG_IPHONE_4G
+#define GeneralStack ((PageTable - 4) + LargeMemoryStart)
+#else
+#define GeneralStack (PageTable - 4)
+#endif
+#define HeapStart (LargeMemoryStart + 0x02000000)
+#ifndef CONFIG_IPHONE_4G
+#define PageTable (RAMEnd - 0x4000)
+#else
+#define PageTable (RAMEnd - 0x8000)
+#endif
+#endif
+
+/*
+ * Devices
+ */
+
+#define PeripheralPort 0x38000000
+#ifdef CONFIG_IPHONE_4G
+#define AMC0 0x84000000
+#define AMC0End 0x84400000
+#define AMC0Higher 0x84C00000
+#define AMC0HigherEnd 0x85000000
+#else
+#ifdef CONFIG_3G
+#define AMC0 0x38500000
+#define ROM 0x50000000
+#else
+#define AMC0 0x22000000
+#define ROM 0x20000000
+#endif
+#endif
+
+#define WDT_CTRL 0x3E300000
+#define WDT_CNT 0x3E300004
+
+#define WDT_INT 0x33
+/*
+ * Values
+ */
+
+#define EDRAM_CLOCKGATE 0x1B
+#define WDT_ENABLE 0x100000
+#define WDT_PRE_SHIFT 16
+#define WDT_PRE_MASK 0xF
+#define WDT_CS_SHIFT 12
+#define WDT_CS_MASK 0x7
+#define WDT_CLR 0xA00
+#define WDT_DIS 0xA5
+#define WDT_INT_EN 0x8000
+
+#define DMA_ALIGN 0x40
+
+#endif
+
View
76 mroib/includes/hardware/timer.h
@@ -0,0 +1,76 @@
+#ifndef HW_TIMER_H
+#define HW_TIMER_H
+
+#include "hardware/s5l8900.h"
+
+// Constants
+#define EventTimer 4
+#ifdef CONFIG_IPOD
+#define PiezoTimer 1
+#endif
+#ifdef CONFIG_3G
+#define VibratorTimer 5
+#endif
+
+// Devices
+
+#ifndef CONFIG_IPHONE_4G
+#define TIMER 0x3E200000
+#else
+#define TIMER 0xBF100000
+#endif
+
+// Registers
+
+#define TIMER_0 0x0
+#define TIMER_1 0x20
+#define TIMER_2 0x40
+#define TIMER_3 0x60
+#define TIMER_4 0xA0
+#define TIMER_5 0xC0
+#define TIMER_6 0xE0
+#define TIMER_CONFIG 0
+#define TIMER_STATE 0x4
+#define TIMER_COUNT_BUFFER 0x8
+#define TIMER_COUNT_BUFFER2 0xC
+#define TIMER_PRESCALER 0x10
+#define TIMER_UNKNOWN3 0x14
+#ifndef CONFIG_IPHONE_4G
+#define TIMER_TICKSHIGH 0x80
+#define TIMER_TICKSLOW 0x84
+#else
+#define TIMER_TICKSHIGH 0x2004
+#define TIMER_TICKSLOW 0x2000
+#endif
+#define TIMER_UNKREG0 0x88
+#define TIMER_UNKREG1 0x8C
+#define TIMER_UNKREG2 0x90
+#define TIMER_UNKREG3 0x94
+#define TIMER_UNKREG4 0x98
+#define TIMER_IRQSTAT 0x10000
+#define TIMER_IRQLATCH 0xF8
+
+// Timer
+#define NUM_TIMERS 7
+#define TIMER_CLOCKGATE 0x25
+#define TIMER_IRQ 0x7
+#define TIMER_STATE_START 1
+#define TIMER_STATE_STOP 0
+#define TIMER_STATE_MANUALUPDATE 2
+#define TIMER_UNKREG0_RESET1 0xA
+#define TIMER_UNKREG0_RESET2 0x18010
+#define TIMER_UNKREG1_RESET 0xFFFFFFFF
+#define TIMER_UNKREG2_RESET 0xFFFFFFFF
+#define TIMER_UNKREG3_RESET 0xFFFFFFFF
+#define TIMER_UNKREG4_RESET 0xFFFFFFFF
+#define TIMER_DIVIDER1 4
+#define TIMER_DIVIDER2 0
+#define TIMER_DIVIDER4 1
+#define TIMER_DIVIDER16 2
+#define TIMER_DIVIDER64 3
+#define TIMER_SPECIALTIMER_BIT0 0x1000000
+#define TIMER_SPECIALTIMER_BIT1 0x2000000
+
+#define TIMER_Separator 4
+
+#endif
View
184 mroib/includes/hardware/usb.h
@@ -0,0 +1,184 @@
+#ifndef HW_USB_H
+#define HW_USB_H
+
+#include "hardware/s5l8900.h"
+
+// Device
+#define USB 0x38400000
+#define USB_PHY 0x3C400000
+
+// Registers
+#define OPHYPWR 0
+#define OPHYCLK 0x4
+#define ORSTCON 0x8
+#define GOTGCTL 0x0
+#define GOTGINT 0x4
+#define GAHBCFG 0x8
+#define GUSBCFG 0xC
+#define GRSTCTL 0x10
+#define GINTSTS 0x14
+#define GINTMSK 0x18
+#define GRXFSIZ 0x24
+#define GNPTXFSIZ 0x28
+#define GNPTXFSTS 0x2C
+#define DIEPMSK 0x810
+#define DOEPMSK 0x814
+#define DAINT 0x818
+#define DAINTMSK 0x81C
+#define USB_INREGS 0x900
+#define USB_OUTREGS 0xB00
+
+#define DCFG 0x800
+#define DCTL 0x804
+#define DSTS 0x808
+
+#define USB_ENDPOINT_DIRECTIONS 0x44
+#define USB_ONOFF 0xE00
+
+// Values
+#define USB_INTERRUPT 0x13
+
+#define USB_OTGCLOCKGATE 0x2
+#define USB_PHYCLOCKGATE 0x23
+#define USB_ONOFF_OFF 3 // bits 0, 1
+
+#define OPHYPWR_FORCESUSPEND 0x1
+#define OPHYPWR_PLLPOWERDOWN 0x2
+#define OPHYPWR_XOPOWERDOWN 0x4
+#define OPHYPWR_ANALOGPOWERDOWN 0x8
+#define OPHYPWR_UNKNOWNPOWERDOWN 0x10
+#define OPHYPWR_POWERON 0x0 // all the previous flags are off
+
+#define OPHYCLK_CLKSEL_MASK 0x3
+#define OPHYCLK_CLKSEL_48MHZ 0x0
+#define OPHYCLK_CLKSEL_12MHZ 0x2
+#define OPHYCLK_CLKSEL_24MHZ 0x3
+
+#define GOTGCTL_BSESSIONVALID (1 << 19)
+#define GOTGCTL_SESSIONREQUEST (1 << 1)
+
+#define ORSTCON_PHYSWRESET 0x1
+#define ORSTCON_LINKSWRESET 0x2
+#define ORSTCON_PHYLINKSWRESET 0x4
+
+#define GAHBCFG_DMAEN (1 << 5)
+#define GAHBCFG_BSTLEN_SINGLE (0 << 1)
+#define GAHBCFG_BSTLEN_INCR (1 << 1)
+#define GAHBCFG_BSTLEN_INCR4 (3 << 1)
+#define GAHBCFG_BSTLEN_INCR8 (5 << 1)
+#define GAHBCFG_BSTLEN_INCR16 (7 << 1)
+#define GAHBCFG_MASKINT 0x1
+
+#define GUSBCFG_TURNAROUND_MASK 0xF
+#define GUSBCFG_TURNAROUND_SHIFT 10
+#define GUSBCFG_HNPENABLE (1 << 9)
+#define GUSBCFG_SRPENABLE (1 << 8)
+#define GUSBCFG_PHYIF16BIT (1 << 3)
+#define USB_UNKNOWNREG1_START 0x1708
+
+#define GRSTCTL_AHBIDLE (1 << 31)
+#define GRSTCTL_CORESOFTRESET 0x1
+
+#define GINTMSK_NONE 0x0
+#define GINTMSK_OTG (1 << 2)
+#define GINTMSK_SOF (1 << 3)
+#define GINTMSK_SUSPEND (1 << 11)
+#define GINTMSK_RESET (1 << 12)
+#define GINTMSK_EPMIS (1 << 17)
+#define GINTMSK_INEP (1 << 18)
+#define GINTMSK_OEP (1 << 19)
+#define GINTMSK_DISCONNECT (1 << 29)
+
+#define RX_FIFO_DEPTH 0x1C0
+#define TX_FIFO_DEPTH 0x1C0
+#define TX_FIFO_STARTADDR 0x200
+
+#define GNPTXFSIZ_DEPTH_SHIFT 16
+
+#define GNPTXFSTS_GET_TXQSPCAVAIL(x) GET_BITS(x, 16, 8)
+
+#define DAINTMSK_ALL 0xFFFFFFFF
+#define DAINTMSK_OUT_SHIFT 16
+#define DAINTMSK_IN_SHIFT 0
+
+#define DCTL_SFTDISCONNECT 0x2
+#define DCTL_SETD0PID (1 << 28)
+#define DCTL_PROGRAMDONE (1 << 11)
+#define DCTL_CGOUTNAK (1 << 10)
+#define DCTL_CGNPINNAK (1 << 8)
+#define DCTL_NEXTEP_MASK 0xF
+#define DCTL_NEXTEP_SHIFT 11
+
+#define DSTS_GET_SPEED(x) GET_BITS(x, 1, 2)
+
+#define DCFG_NZSTSOUTHSHK (1 << 2)
+#define DCFG_HISPEED 0x0
+#define DCFG_FULLSPEED 0x1
+#define DCFG_DEVICEADDR_UNSHIFTED_MASK 0x7F
+#define DCFG_DEVICEADDR_SHIFT 4
+#define DCFG_DEVICEADDRMSK (DCFG_DEVICEADDR_UNSHIFTED_MASK << DCFG_DEVICEADDR_SHIFT)
+
+
+#define DOEPTSIZ0_SUPCNT_MASK 0x3
+#define DOEPTSIZ0_SUPCNT_SHIFT 29
+#define DOEPTSIZ0_PKTCNT_MASK 0x1
+#define DEPTSIZ0_XFERSIZ_MASK 0x7F
+#define DIEPTSIZ_MC_MASK 0x3
+#define DIEPTSIZ_MC_SHIFT 29
+#define DEPTSIZ_PKTCNT_MASK 0x3FF
+#define DEPTSIZ_PKTCNT_SHIFT 19
+#define DEPTSIZ_XFERSIZ_MASK 0x1FFFF
+
+// ENDPOINT_DIRECTIONS register has two bits per endpoint. 0, 1 for endpoint 0. 1, 2 for end point 1, etc.
+#define USB_EP_DIRECTION(ep) ((GET_REG(USB + USB_ENDPOINT_DIRECTIONS) >> ((ep) * 2)) & 0x3)
+#define USB_ENDPOINT_DIRECTIONS_BIDIR 0
+#define USB_ENDPOINT_DIRECTIONS_IN 1
+#define USB_ENDPOINT_DIRECTIONS_OUT 2
+
+#define USB_START_DELAYUS 10000
+#define USB_RESET_DELAYUS 1000
+#define USB_SFTDISCONNECT_DELAYUS 4000
+#define USB_ONOFFSTART_DELAYUS 100
+#define USB_PHYPWRPOWERON_DELAYUS 10
+#define USB_RESET2_DELAYUS 20
+#define USB_RESETWAITFINISH_DELAYUS 1000
+#define USB_SFTCONNECT_DELAYUS 250
+#define USB_PROGRAMDONE_DELAYUS 10
+
+#define USB_EPCON_ENABLE (1 << 31)
+#define USB_EPCON_SETNAK (1 << 27)
+#define USB_EPCON_CLEARNAK (1 << 26)
+#define USB_EPCON_STALL (1 << 21)
+#define USB_EPCON_ACTIVE (1 << 15)
+#define USB_EPCON_TYPE_MASK 0x3
+#define USB_EPCON_TYPE_SHIFT 18
+#define USB_EPCON_MPS_MASK 0x7FF
+
+#define USB_EPINT_INEPNakEff 0x40
+#define USB_EPINT_INTknEPMis 0x20
+#define USB_EPINT_INTknTXFEmp 0x10
+#define USB_EPINT_TimeOUT 0x8
+#define USB_EPINT_AHBErr 0x4
+#define USB_EPINT_EPDisbld 0x2
+#define USB_EPINT_XferCompl 0x1
+
+#define USB_EPINT_Back2BackSetup (1 << 6)
+#define USB_EPINT_OUTTknEPDis 0x10
+#define USB_EPINT_SetUp 0x8
+#define USB_EPINT_EpDisbld 0x1
+#define USB_EPINT_NONE 0
+#define USB_EPINT_ALL 0xFFFFFFFF
+
+#define USB_NUM_ENDPOINTS 6
+
+#define USB_2_0 0x0200
+
+#define USB_HIGHSPEED 0
+#define USB_FULLSPEED 1
+#define USB_LOWSPEED 2
+#define USB_FULLSPEED_48_MHZ 3
+
+#define USB_CONTROLEP 0
+
+#endif
+
View
44 mroib/includes/openiboot.h
@@ -0,0 +1,44 @@
+#ifndef OPENIBOOT_H
+#define OPENIBOOT_H
+
+typedef unsigned long long uint64_t;
+typedef unsigned int uint32_t;
+typedef unsigned short uint16_t;
+typedef unsigned char uint8_t;
+typedef signed long long int64_t;
+typedef signed int int32_t;
+typedef signed short int16_t;
+typedef signed char int8_t;
+typedef long unsigned int size_t;
+typedef signed int intptr_t;
+
+typedef enum Boolean {
+ FALSE = 0,
+ TRUE = 1
+} Boolean;
+
+typedef enum OnOff {
+ OFF = 0,
+ ON = 1
+} OnOff;
+
+#ifndef NULL
+#define NULL 0
+#endif
+#define uSecPerSec 1000000
+
+/*
+ * Macros
+ */
+
+#define GET_REG(x) (*((volatile uint32_t*)(x)))
+#define SET_REG(x, y) (*((volatile uint32_t*)(x)) = (y))
+#define GET_REG32(x) GET_REG(x)
+#define SET_REG32(x, y) SET_REG(x, y)
+#define GET_REG16(x) (*((volatile uint16_t*)(x)))
+#define SET_REG16(x, y) (*((volatile uint16_t*)(x)) = (y))
+#define GET_REG8(x) (*((volatile uint8_t*)(x)))
+#define SET_REG8(x, y) (*((volatile uint8_t*)(x)) = (y))
+#define GET_BITS(x, start, length) ((((uint32_t)(x)) << (32 - ((start) + (length)))) >> (32 - (length)))
+
+#endif
View
9 mroib/includes/power.h
@@ -0,0 +1,9 @@
+#ifndef POWER_H
+#define POWER_H
+
+#include "openiboot.h"
+
+int power_setup();
+int power_ctrl(uint32_t device, OnOff on_off);
+
+#endif
View
12 mroib/includes/timer.h
@@ -0,0 +1,12 @@
+#ifndef TIMER_H
+#define TIMER_H
+
+#include "openiboot.h"
+
+uint64_t timer_get_system_microtime();
+void timer_get_rtc_ticks(uint64_t* ticks, uint64_t* sec_divisor);
+
+void udelay(uint64_t delay);
+
+#endif
+
View
262 mroib/includes/usb.h
@@ -0,0 +1,262 @@
+#ifndef USB_H
+#define USB_H
+
+// assigned by USB Org
+#define VENDOR_APPLE 0x5AC
+
+// assigned by Apple
+#define PRODUCT_IPHONE 0x1280
+#define DEVICE_IPHONE 0x1103
+
+// values we're using
+#define USB_MAX_PACKETSIZE 64
+#define USB_SETUP_PACKETS_AT_A_TIME 1
+#define CONTROL_SEND_BUFFER_LEN 0x80
+#define CONTROL_RECV_BUFFER_LEN 0x80
+#define TX_QUEUE_LEN 0x80
+
+// one packet at a time
+#define USB_MULTICOUNT 1
+
+#define OPENIBOOT_INTERFACE_CLASS 0xFF
+#define OPENIBOOT_INTERFACE_SUBCLASS 0xFF
+#define OPENIBOOT_INTERFACE_PROTOCOL 0x51
+
+#define USB_LANGID_ENGLISH_US 0x0409
+
+#define USBError 0xEEE
+
+typedef enum USBState {
+ USBStart = 0,
+ USBPowered = 1,
+ USBDefault = 2,
+ USBAddress = 3,
+ USBConfigured = 4,
+
+ // Values higher than USBError(0xEEE) are error conditions
+ USBUnknownDescriptorRequest = 0xEEE,
+ USBUnknownRequest = 0xEEF
+} USBState;
+
+typedef enum USBDirection {
+ USBOut = 0,
+ USBIn = 1,
+ USBBiDir = 2
+} USBDirection;
+
+typedef enum USBTransferType {
+ USBControl = 0,
+ USBIsochronous = 1,
+ USBBulk = 2,
+ USBInterrupt = 3
+} USBTransferType;
+
+typedef enum USBSynchronisationType {
+ USBNoSynchronization = 0,
+ USBAsynchronous = 1,
+ USBAdaptive = 2,
+ USBSynchronous = 3
+} USBSynchronisationType;
+
+typedef enum USBUsageType {
+ USBDataEndpoint = 0,
+ USBFeedbackEndpoint = 1,
+ USBExplicitFeedbackEndpoint = 2
+} USBUsageType;
+
+enum USBDescriptorType {
+ USBDeviceDescriptorType = 1,
+ USBConfigurationDescriptorType = 2,
+ USBStringDescriptorType = 3,
+ USBInterfaceDescriptorType = 4,
+ USBEndpointDescriptorType = 5,
+ USBDeviceQualifierDescriptorType = 6
+};
+
+typedef enum USBSpeed {
+ USBHighSpeed = 0,
+ USBFullSpeed = 1,
+ USBLowSpeed = 2
+} USBSpeed;
+
+typedef void (*USBEndpointHandler)(uint32_t token);
+
+typedef struct USBEndpointHandlerInfo {
+ USBEndpointHandler handler;
+ uint32_t token;
+} USBEndpointHandlerInfo;
+
+typedef struct USBEndpointBidirHandlerInfo {
+ USBEndpointHandlerInfo in;
+ USBEndpointHandlerInfo out;
+} USBEndpointBidirHandlerInfo;
+
+typedef struct USBEPRegisters {
+ volatile uint32_t control;
+ volatile uint32_t field_4;
+ volatile uint32_t interrupt;
+ volatile uint32_t field_8;
+ volatile uint32_t transferSize;
+ volatile void* dmaAddress;
+ volatile uint32_t field_18;
+ volatile uint32_t field_1C;
+} USBEPRegisters;
+
+typedef struct USBDeviceDescriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bcdUSB;
+ uint8_t bDeviceClass;
+ uint8_t bDeviceSubClass;
+ uint8_t bDeviceProtocol;
+ uint8_t bMaxPacketSize;
+ uint16_t idVendor;
+ uint16_t idProduct;
+ uint16_t bcdDevice;
+ uint8_t iManufacturer;
+ uint8_t iProduct;
+ uint8_t iSerialNumber;
+ uint8_t bNumConfigurations;
+} __attribute__ ((__packed__)) USBDeviceDescriptor;
+
+typedef struct USBConfigurationDescriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t wTotalLength;
+ uint8_t bNumInterfaces;
+ uint8_t bConfigurationValue;
+ uint8_t iConfiguration;
+ uint8_t bmAttributes;
+ uint8_t bMaxPower;
+} __attribute__ ((__packed__)) USBConfigurationDescriptor;
+
+typedef struct USBInterfaceDescriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bInterfaceNumber;
+ uint8_t bAlternateSetting;
+ uint8_t bNumEndpoints;
+ uint8_t bInterfaceClass;
+ uint8_t bInterfaceSubClass;
+ uint8_t bInterfaceProtocol;
+ uint8_t iInterface;
+} __attribute__ ((__packed__)) USBInterfaceDescriptor;
+
+typedef struct USBEndpointDescriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bEndpointAddress;
+ uint8_t bmAttributes;
+ uint16_t wMaxPacketSize;
+ uint8_t bInterval;
+} __attribute__ ((__packed__)) USBEndpointDescriptor;
+
+typedef struct USBDeviceQualifierDescriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t bcdUSB;
+ uint8_t bDeviceClass;
+ uint8_t bDeviceSubClass;
+ uint8_t bDeviceProtocol;
+ uint8_t bMaxPacketSize;
+ uint8_t bNumConfigurations;
+ uint8_t bReserved;
+} __attribute__ ((__packed__)) USBDeviceQualifierDescriptor;
+
+typedef struct USBStringDescriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ char bString[];
+} __attribute__ ((__packed__)) USBStringDescriptor;
+
+typedef struct USBFirstStringDescriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint16_t wLANGID[];
+} __attribute__ ((__packed__)) USBFirstStringDescriptor;
+
+typedef struct USBInterface {
+ USBInterfaceDescriptor descriptor;
+ USBEndpointDescriptor* endpointDescriptors;
+} USBInterface;
+
+typedef struct USBConfiguration {
+ USBConfigurationDescriptor descriptor;
+ USBInterface* interfaces;
+} USBConfiguration;
+
+typedef struct USBSetupPacket {
+ uint8_t bmRequestType;
+ uint8_t bRequest;
+ uint16_t wValue;
+ uint16_t wIndex;
+ uint16_t wLength;
+} __attribute__ ((__packed__)) USBSetupPacket;
+
+typedef struct RingBuffer {
+ int8_t* writePtr;
+ int8_t* readPtr;
+ uint32_t count;
+ uint32_t size;
+ int8_t* bufferStart;
+ int8_t* bufferEnd;
+} RingBuffer;
+
+typedef void (*USBStartHandler)(void);
+typedef void (*USBEnumerateHandler)(USBInterface* interface);
+
+#define OPENIBOOTCMD_DUMPBUFFER 0
+#define OPENIBOOTCMD_DUMPBUFFER_LEN 1
+#define OPENIBOOTCMD_DUMPBUFFER_GOAHEAD 2
+#define OPENIBOOTCMD_SENDCOMMAND 3
+#define OPENIBOOTCMD_SENDCOMMAND_GOAHEAD 4
+
+typedef struct OpenIBootCmd {
+ uint32_t command;
+ uint32_t dataLen;
+} __attribute__ ((__packed__)) OpenIBootCmd;
+
+#define USBSetupPacketRequestTypeDirection(x) GET_BITS(x, 7, 1)
+#define USBSetupPacketRequestTypeType(x) GET_BITS(x, 5, 2)
+#define USBSetupPacketRequestTypeRecpient(x) GET_BITS(x, 0, 5)
+
+#define USBSetupPacketHostToDevice 0
+#define USBSetupPacketDeviceToHost 1
+#define USBSetupPacketStandard 0
+#define USBSetupPacketClass 1
+#define USBSetupPacketVendor 2
+#define USBSetupPacketRecpientDevice 0
+#define USBSetupPacketRecpientInterface 1
+#define USBSetupPacketRecpientEndpoint 2
+#define USBSetupPacketRecpientOther 3
+
+#define USB_CLEAR_FEATURE 1
+#define USB_GET_CONFIGURATION 8
+#define USB_GET_DESCRIPTOR 6
+#define USB_GET_INTERFACE 10
+#define USB_GET_STATUS 0
+#define USB_SET_ADDRESS 5
+#define USB_SET_CONFIGURATION 9
+#define USB_SET_DESCRIPTOR 7
+#define USB_SET_FEATURE 3
+#define USB_SET_INTERFACE 11
+#define USB_SYNCH_FRAME 12
+
+int usb_setup();
+int usb_start(USBEnumerateHandler hEnumerate, USBStartHandler hStart);
+int usb_shutdown();
+int usb_install_ep_handler(int endpoint, USBDirection direction, USBEndpointHandler handler, uint32_t token);
+void usb_add_endpoint(USBInterface* interface, int endpoint, USBDirection direction, USBTransferType transferType);
+void usb_send_interrupt(uint8_t endpoint, void* buffer, int bufferLen);
+void usb_send_bulk(uint8_t endpoint, void* buffer, int bufferLen);
+void usb_receive_bulk(uint8_t endpoint, void* buffer, int bufferLen);
+void usb_receive_interrupt(uint8_t endpoint, void* buffer, int bufferLen);
+USBSpeed usb_get_speed();
+
+USBDeviceDescriptor* usb_get_device_descriptor();
+USBDeviceQualifierDescriptor* usb_get_device_qualifier_descriptor();
+USBConfigurationDescriptor* usb_get_configuration_descriptor(int index, uint8_t speed_id);
+USBStringDescriptor* usb_get_string_descriptor(int index);
+
+#endif
+
View
52 mroib/includes/util.h
@@ -0,0 +1,52 @@
+#ifndef UTIL_H
+#define UTIL_H
+
+#include "openiboot.h"
+#include <config/config.h>
+
+#ifdef DEBUG
+#define DebugPrintf bufferPrintf
+#else
+#define DebugPrintf(...)
+#endif
+
+void *kern_os_malloc(size_t);
+void kern_os_free(void *);
+void *kern_os_realloc(void *, size_t);
+#define malloc kern_os_malloc
+#define free kern_os_free
+#define realloc kern_os_realloc
+extern void *IOMallocAligned(uint32_t, uint32_t);
+
+static void *memset(void *b, int c, size_t len) {
+ unsigned char *p = b;
+ unsigned char q = c;
+ while(len--) *p++ = q;
+ return b;
+}
+
+static inline void *calloc(size_t count, size_t size) {
+ void *result = malloc(count * size);
+ memset(result, 0, count * size);
+ return result;
+}
+
+static inline size_t strlen(const char* str) {
+ size_t result = 0;
+ while(*str++) result++;
+ return result;
+}
+
+static inline void *memcpy(void *dest, const void *src, uint32_t size) {
+ char *p = dest;
+ const char *q = src;
+ while(size--) *p++ = *q++;
+ return dest;
+}
+
+void CleanAndInvalidateCPUDataCache(void *buffer, int bufferLen);
+
+#define EnterCriticalSection()
+#define LeaveCriticalSection()
+
+#endif
View
69 mroib/mroib.c
@@ -0,0 +1,69 @@
+#include "openiboot.h"
+#include "util.h"
+#include "usb.h"
+#include "hardware/s5l8900.h"
+
+
+static void control_received(uint32_t token) {
+}
+static void data_received(uint32_t token) {
+}
+static void control_sent(uint32_t token) {
+}
+static void data_sent(uint32_t token) {
+}
+
+static int USB_BYTES_AT_A_TIME = 0;
+
+static uint8_t send_buffer[32] __attribute__((aligned(DMA_ALIGN)));
+static uint8_t recv_buffer[32] __attribute__((aligned(DMA_ALIGN)));
+
+static void enumerate_handler(USBInterface* interface) {
+ usb_add_endpoint(interface, 1, USBIn, USBInterrupt);
+ usb_add_endpoint(interface, 2, USBOut, USBInterrupt);
+}
+
+static void start_handler() {
+ if(usb_get_speed() == USBHighSpeed) {
+ USB_BYTES_AT_A_TIME = 512;
+ } else {
+ USB_BYTES_AT_A_TIME = 0x80;
+ }
+
+ usb_receive_interrupt(2, recv_buffer, 1);
+}
+
+static void mr_setup() {
+ static Boolean did_mr_setup = FALSE;
+ if(did_mr_setup) return;
+ did_mr_setup = TRUE;
+
+ usb_setup();
+ usb_install_ep_handler(4, USBOut, control_received, 0);
+ usb_install_ep_handler(2, USBOut, data_received, 0);
+ usb_install_ep_handler(3, USBIn, control_sent, 0);
+ usb_install_ep_handler(1, USBIn, data_sent, 0);
+ usb_start(enumerate_handler, start_handler);
+}
+
+static int mr_getc() {
+ return 0;
+}
+
+static void mr_putc(char c) {
+
+}
+
+extern uint32_t serial_init[];
+extern uint32_t serial_putc[];
+extern uint32_t serial_getc[];
+
+__attribute__((constructor))
+static void init() {
+ serial_init[0] = 0xe51ff004;
+ serial_init[1] = (uint32_t) &mr_setup;
+ serial_putc[0] = 0x47184b00;
+ serial_putc[1] = (uint32_t) &mr_putc;
+ serial_getc[0] = 0x47184b00;
+ serial_getc[1] = (uint32_t) &mr_getc;
+}
View
31 mroib/power.c
@@ -0,0 +1,31 @@
+#include "openiboot.h"
+#include "power.h"
+#include "hardware/power.h"
+
+int power_ctrl(uint32_t device, OnOff on_off) {
+#ifndef CONFIG_IPHONE_4G
+ if(on_off == ON) {
+ SET_REG(POWER + POWER_ONCTRL, device);
+ } else {
+ SET_REG(POWER + POWER_OFFCTRL, device);
+ }
+
+ /* wait for the new state to take effect */
+ while((GET_REG(POWER + POWER_SETSTATE) & device) != (GET_REG(POWER + POWER_STATE) & device));
+#else
+ if (device > POWER_STATE_MAX) {
+ return -1;
+ }
+ uint32_t device_register = POWER + POWER_STATE + (device << 2);
+
+ if (on_off == ON) {
+ SET_REG(device_register, GET_REG(device_register) | 0xF);
+ } else {
+ SET_REG(device_register, GET_REG(device_register) & ~0xF);
+ }
+
+ /* wait for the new state to take effect */
+ while ((GET_REG(device_register) & 0xF) != ((GET_REG(device_register) >> 4) & 0xF));
+#endif
+ return 0;
+}
View
BIN  mroib/power.o
Binary file not shown
View
36 mroib/timer.c
@@ -0,0 +1,36 @@
+#include "openiboot.h"
+#include "timer.h"
+#include "hardware/timer.h"
+
+
+uint64_t timer_get_system_microtime() {
+ uint64_t ticks;
+ uint64_t sec_divisor;
+
+ timer_get_rtc_ticks(&ticks, &sec_divisor);
+ return (ticks * uSecPerSec)/sec_divisor;
+}
+
+void timer_get_rtc_ticks(uint64_t* ticks, uint64_t* sec_divisor) {
+ register uint32_t ticksHigh;
+ register uint32_t ticksLow;
+ register uint32_t ticksHigh2;
+
+ /* try to get a good read where the lower bits remain the same after reading the higher bits */
+ do {
+ ticksHigh = GET_REG(TIMER + TIMER_TICKSHIGH);
+ ticksLow = GET_REG(TIMER + TIMER_TICKSLOW);
+ ticksHigh2 = GET_REG(TIMER + TIMER_TICKSHIGH);
+ } while(ticksHigh != ticksHigh2);
+
+ *ticks = (((uint64_t)ticksHigh) << 32) | ticksLow;
+ *sec_divisor = 0x16E3600;//TicksPerSec;
+}
+
+void udelay(uint64_t delay) {
+ uint64_t startTime = timer_get_system_microtime();
+
+ // loop while elapsed time is less than requested delay
+ while((timer_get_system_microtime() - startTime) < delay);
+}
+
View
1,103 mroib/usb.c
@@ -0,0 +1,1103 @@
+#include "openiboot.h"
+#include "usb.h"
+#include "power.h"
+#include "util.h"
+#include "hardware/power.h"
+#include "hardware/usb.h"
+#include "timer.h"
+
+static void change_state(USBState new_state);
+
+static Boolean usb_inited;
+
+static USBState usb_state;
+static uint8_t usb_speed;
+static uint8_t usb_max_packet_size;
+static USBDirection *endpoint_directions;//[USB_NUM_ENDPOINTS];
+static USBEndpointBidirHandlerInfo *endpoint_handlers;//[USB_NUM_ENDPOINTS];
+static uint32_t *inInterruptStatus;//[USB_NUM_ENDPOINTS];
+static uint32_t *outInterruptStatus;//[USB_NUM_ENDPOINTS];
+
+USBEPRegisters* InEPRegs;
+USBEPRegisters* OutEPRegs;
+
+static uint8_t currentlySending;
+
+static USBDeviceDescriptor deviceDescriptor;
+static USBDeviceQualifierDescriptor deviceQualifierDescriptor;
+
+static uint8_t numStringDescriptors;
+static USBStringDescriptor** stringDescriptors;
+static USBFirstStringDescriptor* firstStringDescriptor;
+
+static USBConfiguration* configurations;
+
+static uint8_t* controlSendBuffer = NULL;
+static uint8_t* controlRecvBuffer = NULL;
+
+static RingBuffer* txQueue = NULL;
+
+static USBEnumerateHandler enumerateHandler;
+static USBStartHandler startHandler;
+
+static void usbIRQHandler(uint32_t token);
+
+static void initializeDescriptors();
+
+static uint8_t addConfiguration(uint8_t bConfigurationValue, uint8_t iConfiguration, uint8_t selfPowered, uint8_t remoteWakeup, uint16_t maxPower);
+
+static void endConfiguration(USBConfiguration* configuration);
+
+static USBInterface* addInterfaceDescriptor(USBConfiguration* configuration, uint8_t interface, uint8_t bAlternateSetting, uint8_t bInterfaceClass, uint8_t bInterfaceSubClass, uint8_t bInterfaceProtocol, uint8_t iInterface);
+
+static uint8_t addEndpointDescriptor(USBInterface* interface, uint8_t endpoint, USBDirection direction, USBTransferType transferType, USBSynchronisationType syncType, USBUsageType usageType, uint16_t wMaxPacketSize, uint8_t bInterval);
+
+static void releaseConfigurations();
+
+static uint8_t addStringDescriptor(const char* descriptorString);
+static void releaseStringDescriptors();
+static uint16_t packetsizeFromSpeed(uint8_t speed_id);
+
+static void sendControl(void* buffer, int bufferLen);
+static void receiveControl(void* buffer, int bufferLen);
+
+static void receive(int endpoint, USBTransferType transferType, void* buffer, int packetLength, int bufferLen);
+
+static int resetUSB();
+static void getEndpointInterruptStatuses();
+static void callEndpointHandlers();
+static uint32_t getConfigurationTree(int i, uint8_t speed_id, void* buffer);
+static void setConfiguration(int i);
+
+static void handleTxInterrupts(int endpoint);
+static void handleRxInterrupts(int endpoint);
+
+static int advanceTxQueue();
+
+static RingBuffer* createRingBuffer(int size);
+static int8_t ringBufferDequeue(RingBuffer* buffer);
+static int8_t ringBufferEnqueue(RingBuffer* buffer, uint8_t value);
+
+static void usbTxRx(int endpoint, USBDirection direction, USBTransferType transferType, void* buffer, int bufferLen);
+
+int usb_setup() {
+ int i;
+
+ if(usb_inited) {
+ return 0;
+ }
+
+ endpoint_directions = calloc(sizeof(*endpoint_directions), USB_NUM_ENDPOINTS);
+ endpoint_handlers = calloc(sizeof(*endpoint_handlers), USB_NUM_ENDPOINTS);
+ inInterruptStatus = calloc(sizeof(*inInterruptStatus), USB_NUM_ENDPOINTS);
+ outInterruptStatus = calloc(sizeof(*outInterruptStatus), USB_NUM_ENDPOINTS);
+
+ InEPRegs = (USBEPRegisters*)(USB + USB_INREGS);
+ OutEPRegs = (USBEPRegisters*)(USB + USB_OUTREGS);
+
+ change_state(USBStart);
+
+ // Power on hardware
+ power_ctrl(POWER_USB, ON);
+ udelay(USB_START_DELAYUS);
+
+ // Initialize our data structures
+ for(i = 0; i < USB_NUM_ENDPOINTS; i++) {
+ switch(USB_EP_DIRECTION(i)) {
+ case USB_ENDPOINT_DIRECTIONS_BIDIR:
+ endpoint_directions[i] = USBBiDir;
+ break;
+ case USB_ENDPOINT_DIRECTIONS_IN:
+ endpoint_directions[i] = USBIn;
+ break;
+ case USB_ENDPOINT_DIRECTIONS_OUT:
+ endpoint_directions[i] = USBOut;
+ break;
+ }
+ //bufferPrintf("EP %d: %d\r\n", i, endpoint_directions[i]);
+ }
+
+ memset(endpoint_handlers, 0, sizeof(endpoint_handlers));
+
+ // Set up the hardware
+ power_ctrl(USB_OTGCLOCKGATE, ON);
+ power_ctrl(USB_PHYCLOCKGATE, ON);
+ power_ctrl(EDRAM_CLOCKGATE, ON);
+
+ // Generate a soft disconnect on host
+ SET_REG(USB + DCTL, GET_REG(USB + DCTL) | DCTL_SFTDISCONNECT);
+ udelay(USB_SFTDISCONNECT_DELAYUS);
+
+ // power on OTG
+ SET_REG(USB + USB_ONOFF, GET_REG(USB + USB_ONOFF) & (~USB_ONOFF_OFF));
+ udelay(USB_ONOFFSTART_DELAYUS);
+
+ // power on PHY
+ SET_REG(USB_PHY + OPHYPWR, OPHYPWR_POWERON);
+ udelay(USB_PHYPWRPOWERON_DELAYUS);
+
+ // select clock
+ SET_REG(USB_PHY + OPHYCLK, (GET_REG(USB_PHY + OPHYCLK) & (~OPHYCLK_CLKSEL_MASK)) | OPHYCLK_CLKSEL_48MHZ);
+
+ // reset phy
+ SET_REG(USB_PHY + ORSTCON, GET_REG(USB_PHY + ORSTCON) | ORSTCON_PHYSWRESET);
+ udelay(USB_RESET2_DELAYUS);
+ SET_REG(USB_PHY + ORSTCON, GET_REG(USB_PHY + ORSTCON) & (~ORSTCON_PHYSWRESET));
+ udelay(USB_RESET_DELAYUS);
+
+ SET_REG(USB + GRSTCTL, GRSTCTL_CORESOFTRESET);
+
+ // wait until reset takes
+ while((GET_REG(USB + GRSTCTL) & GRSTCTL_CORESOFTRESET) == GRSTCTL_CORESOFTRESET);
+
+ // wait until reset completes
+ while((GET_REG(USB + GRSTCTL) & ~GRSTCTL_AHBIDLE) != 0);
+
+ udelay(USB_RESETWAITFINISH_DELAYUS);
+
+ // allow host to reconnect
+ SET_REG(USB + DCTL, GET_REG(USB + DCTL) & (~DCTL_SFTDISCONNECT));
+ udelay(USB_SFTCONNECT_DELAYUS);
+
+ // flag all interrupts as positive, maybe to disable them
+
+ // Set 7th EP? This is what iBoot does
+ InEPRegs[USB_NUM_ENDPOINTS].interrupt = USB_EPINT_INEPNakEff | USB_EPINT_INTknEPMis | USB_EPINT_INTknTXFEmp
+ | USB_EPINT_TimeOUT | USB_EPINT_AHBErr | USB_EPINT_EPDisbld | USB_EPINT_XferCompl;
+ OutEPRegs[USB_NUM_ENDPOINTS].interrupt = USB_EPINT_OUTTknEPDis
+ | USB_EPINT_SetUp | USB_EPINT_AHBErr | USB_EPINT_EPDisbld | USB_EPINT_XferCompl;
+
+ for(i = 0; i < USB_NUM_ENDPOINTS; i++) {
+ InEPRegs[i].interrupt = USB_EPINT_INEPNakEff | USB_EPINT_INTknEPMis | USB_EPINT_INTknTXFEmp
+ | USB_EPINT_TimeOUT | USB_EPINT_AHBErr | USB_EPINT_EPDisbld | USB_EPINT_XferCompl;
+ OutEPRegs[i].interrupt = USB_EPINT_OUTTknEPDis
+ | USB_EPINT_SetUp | USB_EPINT_AHBErr | USB_EPINT_EPDisbld | USB_EPINT_XferCompl;
+ }
+
+ // disable all interrupts until endpoint descriptors and configuration structures have been setup
+ SET_REG(USB + GINTMSK, GINTMSK_NONE);
+ SET_REG(USB + DIEPMSK, USB_EPINT_NONE);
+ SET_REG(USB + DOEPMSK, USB_EPINT_NONE);
+
+ //interrupt_install(USB_INTERRUPT, usbIRQHandler, 0);
+
+ usb_inited = TRUE;
+
+ return 0;
+}
+
+int usb_start(USBEnumerateHandler hEnumerate, USBStartHandler hStart) {
+ enumerateHandler = hEnumerate;
+ startHandler = hStart;
+ currentlySending = 0xFF;
+
+ if(txQueue == NULL)
+ txQueue = createRingBuffer(TX_QUEUE_LEN);
+
+ initializeDescriptors();
+
+ if(controlSendBuffer == NULL)
+ controlSendBuffer = IOMallocAligned(CONTROL_SEND_BUFFER_LEN, DMA_ALIGN);
+
+ if(controlRecvBuffer == NULL)
+ controlRecvBuffer = IOMallocAligned(CONTROL_RECV_BUFFER_LEN, DMA_ALIGN);
+
+ SET_REG(USB + GAHBCFG, GAHBCFG_DMAEN | GAHBCFG_BSTLEN_INCR8 | GAHBCFG_MASKINT);
+ SET_REG(USB + GUSBCFG, GUSBCFG_PHYIF16BIT | GUSBCFG_SRPENABLE | GUSBCFG_HNPENABLE | ((5 & GUSBCFG_TURNAROUND_MASK) << GUSBCFG_TURNAROUND_SHIFT));
+ SET_REG(USB + DCFG, DCFG_HISPEED); // some random setting. See specs
+ SET_REG(USB + DCFG, GET_REG(USB + DCFG) & ~(DCFG_DEVICEADDRMSK));
+ InEPRegs[0].control = USB_EPCON_ACTIVE;
+ OutEPRegs[0].control = USB_EPCON_ACTIVE;
+
+ SET_REG(USB + GRXFSIZ, RX_FIFO_DEPTH);
+ SET_REG(USB + GNPTXFSIZ, (TX_FIFO_DEPTH << GNPTXFSIZ_DEPTH_SHIFT) | TX_FIFO_STARTADDR);
+
+ int i;
+ for(i = 0; i < USB_NUM_ENDPOINTS; i++) {
+ InEPRegs[i].interrupt = USB_EPINT_INEPNakEff | USB_EPINT_INTknEPMis | USB_EPINT_INTknTXFEmp
+ | USB_EPINT_TimeOUT | USB_EPINT_AHBErr | USB_EPINT_EPDisbld | USB_EPINT_XferCompl;
+ OutEPRegs[i].interrupt = USB_EPINT_OUTTknEPDis
+ | USB_EPINT_SetUp | USB_EPINT_AHBErr | USB_EPINT_EPDisbld | USB_EPINT_XferCompl;
+
+ }
+
+ SET_REG(USB + GINTMSK, GINTMSK_OTG | GINTMSK_SUSPEND | GINTMSK_RESET | GINTMSK_INEP | GINTMSK_OEP | GINTMSK_DISCONNECT);
+ SET_REG(USB + DAINTMSK, DAINTMSK_ALL);
+
+ SET_REG(USB + DOEPMSK, USB_EPINT_XferCompl | USB_EPINT_SetUp | USB_EPINT_Back2BackSetup);
+ SET_REG(USB + DIEPMSK, USB_EPINT_XferCompl | USB_EPINT_AHBErr | USB_EPINT_TimeOUT);
+
+ InEPRegs[0].interrupt = USB_EPINT_ALL;
+ OutEPRegs[0].interrupt = USB_EPINT_ALL;
+
+ SET_REG(USB + DCTL, DCTL_PROGRAMDONE + DCTL_CGOUTNAK + DCTL_CGNPINNAK);
+ udelay(USB_PROGRAMDONE_DELAYUS);
+ SET_REG(USB + GOTGCTL, GET_REG(USB + GOTGCTL) | GOTGCTL_SESSIONREQUEST);
+
+ receiveControl(controlRecvBuffer, sizeof(USBSetupPacket));
+
+ change_state(USBPowered);
+
+ //interrupt_enable(USB_INTERRUPT);
+
+ return 0;
+}
+
+static void receiveControl(void* buffer, int bufferLen) {
+ CleanAndInvalidateCPUDataCache(buffer, bufferLen);
+ receive(USB_CONTROLEP, USBControl, buffer, USB_MAX_PACKETSIZE, bufferLen);
+}
+
+static void usbTxRx(int endpoint, USBDirection direction, USBTransferType transferType, void* buffer, int bufferLen) {
+ int packetLength;
+
+ if(transferType == USBControl || transferType == USBInterrupt) {
+ packetLength = USB_MAX_PACKETSIZE;
+ } else {
+ packetLength = packetsizeFromSpeed(usb_speed);
+ }
+
+ CleanAndInvalidateCPUDataCache(buffer, bufferLen);
+
+ if(direction == USBOut) {
+ receive(endpoint, transferType, buffer, packetLength, bufferLen);
+ return;
+ }
+
+ if(GNPTXFSTS_GET_TXQSPCAVAIL(GET_REG(USB + GNPTXFSTS)) == 0) {
+ // no space available
+ return;
+ }
+
+ // enable interrupts for this endpoint
+ SET_REG(USB + DAINTMSK, GET_REG(USB + DAINTMSK) | ((1 << endpoint) << DAINTMSK_IN_SHIFT));
+
+ InEPRegs[endpoint].dmaAddress = buffer;
+
+ if(endpoint == USB_CONTROLEP) {
+ // we'll only send one packet at a time on CONTROLEP
+ InEPRegs[endpoint].transferSize = ((1 & DEPTSIZ_PKTCNT_MASK) << DEPTSIZ_PKTCNT_SHIFT) | (bufferLen & DEPTSIZ0_XFERSIZ_MASK);
+ InEPRegs[endpoint].control = USB_EPCON_CLEARNAK;
+ return;
+ }
+
+ int packetCount = bufferLen / packetLength;
+ if((bufferLen % packetLength) != 0)
+ ++packetCount;
+
+
+ InEPRegs[endpoint].transferSize = ((packetCount & DEPTSIZ_PKTCNT_MASK) << DEPTSIZ_PKTCNT_SHIFT)
+ | (bufferLen & DEPTSIZ_XFERSIZ_MASK) | ((USB_MULTICOUNT & DIEPTSIZ_MC_MASK) << DIEPTSIZ_MC_SHIFT);
+
+
+ InEPRegs[endpoint].control = USB_EPCON_CLEARNAK | USB_EPCON_ACTIVE | ((transferType & USB_EPCON_TYPE_MASK) << USB_EPCON_TYPE_SHIFT) | (packetLength & USB_EPCON_MPS_MASK);
+
+}
+
+static void receive(int endpoint, USBTransferType transferType, void* buffer, int packetLength, int bufferLen) {
+ if(endpoint == USB_CONTROLEP) {
+ OutEPRegs[endpoint].transferSize = ((USB_SETUP_PACKETS_AT_A_TIME & DOEPTSIZ0_SUPCNT_MASK) << DOEPTSIZ0_SUPCNT_SHIFT)
+ | ((USB_SETUP_PACKETS_AT_A_TIME & DOEPTSIZ0_PKTCNT_MASK) << DEPTSIZ_PKTCNT_SHIFT) | (bufferLen & DEPTSIZ0_XFERSIZ_MASK);
+ } else {
+ // divide our buffer into packets. Apple uses fancy bitwise arithmetic while we call huge libgcc integer arithmetic functions
+ // for the sake of code readability. Will this matter?
+ int packetCount = bufferLen / packetLength;
+ if((bufferLen % packetLength) != 0)
+ ++packetCount;
+
+ OutEPRegs[endpoint].transferSize = ((packetCount & DEPTSIZ_PKTCNT_MASK) << DEPTSIZ_PKTCNT_SHIFT) | (bufferLen & DEPTSIZ_XFERSIZ_MASK);
+ }
+
+ SET_REG(USB + DAINTMSK, GET_REG(USB + DAINTMSK) | (1 << (DAINTMSK_OUT_SHIFT + endpoint)));
+
+ OutEPRegs[endpoint].dmaAddress = buffer;
+
+ // start the transfer
+ OutEPRegs[endpoint].control = USB_EPCON_ENABLE | USB_EPCON_CLEARNAK | USB_EPCON_ACTIVE
+ | ((transferType & USB_EPCON_TYPE_MASK) << USB_EPCON_TYPE_SHIFT) | (packetLength & USB_EPCON_MPS_MASK);
+}
+
+static int resetUSB() {
+ SET_REG(USB + DCFG, GET_REG(USB + DCFG) & ~DCFG_DEVICEADDRMSK);
+
+ int endpoint;
+ for(endpoint = 0; endpoint < USB_NUM_ENDPOINTS; endpoint++) {
+ OutEPRegs[endpoint].control = OutEPRegs[endpoint].control | USB_EPCON_SETNAK;
+ }
+
+ // enable interrupts for endpoint 0
+ SET_REG(USB + DAINTMSK, GET_REG(USB + DAINTMSK) | ((1 << USB_CONTROLEP) << DAINTMSK_OUT_SHIFT) | ((1 << USB_CONTROLEP) << DAINTMSK_IN_SHIFT));
+
+ SET_REG(USB + DOEPMSK, USB_EPINT_XferCompl | USB_EPINT_SetUp | USB_EPINT_Back2BackSetup);
+ SET_REG(USB + DIEPMSK, USB_EPINT_XferCompl | USB_EPINT_AHBErr | USB_EPINT_TimeOUT);
+
+ receiveControl(controlRecvBuffer, sizeof(USBSetupPacket));
+
+ return 0;
+}
+
+static void getEndpointInterruptStatuses() {
+ // To not mess up the interrupt controller, we can only read the interrupt status once per interrupt, so we need to cache them here
+ int endpoint;
+ for(endpoint = 0; endpoint < USB_NUM_ENDPOINTS; endpoint++) {
+ if(endpoint_directions[endpoint] == USBIn || endpoint_directions[endpoint] == USBBiDir) {
+ inInterruptStatus[endpoint] = InEPRegs[endpoint].interrupt;
+ }
+ if(endpoint_directions[endpoint] == USBOut || endpoint_directions[endpoint] == USBBiDir) {
+ outInterruptStatus[endpoint] = OutEPRegs[endpoint].interrupt;
+ }
+ }
+}
+
+static int isSetupPhaseDone() {
+ uint32_t status = GET_REG(USB + DAINTMSK);
+ int isDone = FALSE;
+
+ if((status & ((1 << USB_CONTROLEP) << DAINTMSK_OUT_SHIFT)) == ((1 << USB_CONTROLEP) << DAINTMSK_OUT_SHIFT)) {
+ if((outInterruptStatus[USB_CONTROLEP] & USB_EPINT_SetUp) == USB_EPINT_SetUp) {
+ isDone = TRUE;
+ }
+ }
+
+ // clear interrupt
+ OutEPRegs[USB_CONTROLEP].interrupt = USB_EPINT_SetUp;
+
+ return isDone;
+}
+
+static void callEndpointHandlers() {
+ uint32_t status = GET_REG(USB + DAINTMSK);
+
+ int endpoint;
+ for(endpoint = 0; endpoint < USB_NUM_ENDPOINTS; endpoint++) {
+ if((status & ((1 << endpoint) << DAINTMSK_OUT_SHIFT)) == ((1u << endpoint) << DAINTMSK_OUT_SHIFT)) {
+ if((outInterruptStatus[endpoint] & USB_EPINT_XferCompl) == USB_EPINT_XferCompl) {
+ if(endpoint_handlers[endpoint].out.handler != NULL) {
+ endpoint_handlers[endpoint].out.handler(endpoint_handlers[endpoint].out.token);
+ }
+ }
+ }
+
+ if((status & ((1 << endpoint) << DAINTMSK_IN_SHIFT)) == ((1u << endpoint) << DAINTMSK_IN_SHIFT)) {
+ if((inInterruptStatus[endpoint] & USB_EPINT_XferCompl) == USB_EPINT_XferCompl) {
+ if(endpoint_handlers[endpoint].in.handler != NULL) {
+ endpoint_handlers[endpoint].in.handler(endpoint_handlers[endpoint].in.token);
+ }
+ }
+ }
+
+ if(endpoint_directions[endpoint] == USBOut || endpoint_directions[endpoint] == USBBiDir) {
+ handleRxInterrupts(endpoint);
+ }
+
+ if(endpoint_directions[endpoint] == USBIn || endpoint_directions[endpoint] == USBBiDir) {
+ handleTxInterrupts(endpoint);
+ }
+ }
+}
+
+static void handleTxInterrupts(int endpoint) {
+ if(!inInterruptStatus[endpoint]) {
+ return;
+ }
+
+ //uartPrintf("\tendpoint %d has an TX interrupt\r\n", endpoint);
+
+ // clear pending interrupts
+ if((inInterruptStatus[endpoint] & USB_EPINT_INEPNakEff) == USB_EPINT_INEPNakEff) {
+ InEPRegs[endpoint].interrupt = USB_EPINT_INEPNakEff;
+ //uartPrintf("\t\tUSB_EPINT_INEPNakEff\r\n");
+ }
+
+ if((inInterruptStatus[endpoint] & USB_EPINT_INTknEPMis) == USB_EPINT_INTknEPMis) {
+ InEPRegs[endpoint].interrupt = USB_EPINT_INTknEPMis;
+ //uartPrintf("\t\tUSB_EPINT_INTknEPMis\r\n");
+
+ // clear the corresponding core interrupt
+ SET_REG(USB + GINTSTS, GET_REG(USB + GINTSTS) | GINTMSK_EPMIS);
+ }
+
+ if((inInterruptStatus[endpoint] & USB_EPINT_INTknTXFEmp) == USB_EPINT_INTknTXFEmp) {
+ InEPRegs[endpoint].interrupt = USB_EPINT_INTknTXFEmp;
+ //uartPrintf("\t\tUSB_EPINT_INTknTXFEmp\r\n");
+ }
+
+ if((inInterruptStatus[endpoint] & USB_EPINT_TimeOUT) == USB_EPINT_TimeOUT) {
+ InEPRegs[endpoint].interrupt = USB_EPINT_TimeOUT;
+ //uartPrintf("\t\tUSB_EPINT_TimeOUT\r\n");
+ currentlySending = 0xFF;
+ //ringBufferDequeue(txQueue);
+ }
+
+ if((inInterruptStatus[endpoint] & USB_EPINT_AHBErr) == USB_EPINT_AHBErr) {
+ InEPRegs[endpoint].interrupt = USB_EPINT_AHBErr;
+ //uartPrintf("\t\tUSB_EPINT_AHBErr\r\n");
+ }
+
+ if((inInterruptStatus[endpoint] & USB_EPINT_EPDisbld) == USB_EPINT_EPDisbld) {
+ InEPRegs[endpoint].interrupt = USB_EPINT_EPDisbld;
+ //uartPrintf("\t\tUSB_EPINT_EPDisbldr\n");
+ }
+
+ if((inInterruptStatus[endpoint] & USB_EPINT_XferCompl) == USB_EPINT_XferCompl) {
+ InEPRegs[endpoint].interrupt = USB_EPINT_XferCompl;
+ //uartPrintf("\t\tUSB_EPINT_XferCompl\n");
+ currentlySending = 0xFF;
+ advanceTxQueue();
+ }
+
+}
+
+static void handleRxInterrupts(int endpoint) {
+ if(!outInterruptStatus[endpoint]) {
+ return;
+ }
+
+ //uartPrintf("\tendpoint %d has an RX interrupt\r\n", endpoint);
+
+ if((outInterruptStatus[endpoint] & USB_EPINT_Back2BackSetup) == USB_EPINT_Back2BackSetup) {
+ OutEPRegs[endpoint].interrupt = USB_EPINT_Back2BackSetup;
+ }
+
+ if((outInterruptStatus[endpoint] & USB_EPINT_OUTTknEPDis) == USB_EPINT_OUTTknEPDis) {
+ OutEPRegs[endpoint].interrupt = USB_EPINT_OUTTknEPDis;
+ }
+
+ if((outInterruptStatus[endpoint] & USB_EPINT_AHBErr) == USB_EPINT_AHBErr) {
+ OutEPRegs[endpoint].interrupt = USB_EPINT_AHBErr;
+ }
+
+ if((outInterruptStatus[endpoint] & USB_EPINT_EPDisbld) == USB_EPINT_EPDisbld) {
+ OutEPRegs[endpoint].interrupt = USB_EPINT_EPDisbld;
+ }
+
+ if((outInterruptStatus[endpoint] & USB_EPINT_XferCompl) == USB_EPINT_XferCompl) {
+ OutEPRegs[endpoint].interrupt = USB_EPINT_XferCompl;
+ if(endpoint == 0) {
+ receiveControl(controlRecvBuffer, sizeof(USBSetupPacket));
+ }
+ }
+}
+
+static void sendControl(void* buffer, int bufferLen) {
+ usbTxRx(USB_CONTROLEP, USBIn, USBControl, buffer, bufferLen);
+ ringBufferEnqueue(txQueue, USB_CONTROLEP);
+ advanceTxQueue();
+}
+
+static void stallControl(void) {
+ InEPRegs[USB_CONTROLEP].control = USB_EPCON_STALL;
+}
+
+void usb_send_bulk(uint8_t endpoint, void* buffer, int bufferLen) {
+ usbTxRx(endpoint, USBIn, USBBulk, buffer, bufferLen);
+ ringBufferEnqueue(txQueue, endpoint);
+ advanceTxQueue();
+}
+
+void usb_send_interrupt(uint8_t endpoint, void* buffer, int bufferLen) {
+ usbTxRx(endpoint, USBIn, USBInterrupt, buffer, bufferLen);
+ ringBufferEnqueue(txQueue, endpoint);
+ advanceTxQueue();
+}
+
+
+void usb_receive_bulk(uint8_t endpoint, void* buffer, int bufferLen) {
+ usbTxRx(endpoint, USBOut, USBBulk, buffer, bufferLen);
+}
+
+void usb_receive_interrupt(uint8_t endpoint, void* buffer, int bufferLen) {
+ usbTxRx(endpoint, USBOut, USBInterrupt, buffer, bufferLen);
+}
+
+
+static int advanceTxQueue() {
+ EnterCriticalSection();
+ if(currentlySending != 0xFF) {
+ LeaveCriticalSection();
+ return -1;
+ }
+
+ int8_t nextEP = ringBufferDequeue(txQueue);
+ if(nextEP < 0) {
+ LeaveCriticalSection();
+ return -1;
+ }
+
+ currentlySending = nextEP;
+ LeaveCriticalSection();
+
+ /*int endpoint;
+ for(endpoint = 0; endpoint < USB_NUM_ENDPOINTS; endpoint++) {
+ if(endpoint_directions[endpoint] == USBIn || endpoint_directions[endpoint] == USBBiDir) {
+ InEPRegs[endpoint].control = (InEPRegs[endpoint].control & ~(DCTL_NEXTEP_MASK << DCTL_NEXTEP_SHIFT)) | ((nextEP & DCTL_NEXTEP_MASK) << DCTL_NEXTEP_SHIFT);
+ }
+ }*/
+
+ InEPRegs[0].control = (InEPRegs[0].control & ~(DCTL_NEXTEP_MASK << DCTL_NEXTEP_SHIFT)) | ((nextEP & DCTL_NEXTEP_MASK) << DCTL_NEXTEP_SHIFT);
+ InEPRegs[1].control = (InEPRegs[1].control & ~(DCTL_NEXTEP_MASK << DCTL_NEXTEP_SHIFT)) | ((nextEP & DCTL_NEXTEP_MASK) << DCTL_NEXTEP_SHIFT);
+ InEPRegs[3].control = (InEPRegs[3].control & ~(DCTL_NEXTEP_MASK << DCTL_NEXTEP_SHIFT)) | ((nextEP & DCTL_NEXTEP_MASK) << DCTL_NEXTEP_SHIFT);
+ InEPRegs[5].control = (InEPRegs[5].control & ~(DCTL_NEXTEP_MASK << DCTL_NEXTEP_SHIFT)) | ((nextEP & DCTL_NEXTEP_MASK) << DCTL_NEXTEP_SHIFT);
+
+ // clear all the interrupts
+ InEPRegs[nextEP].interrupt = USB_EPINT_ALL;
+
+ // we're ready to transmit!
+ uint32_t controlStatus = InEPRegs[nextEP].control;
+ InEPRegs[nextEP].control = controlStatus | USB_EPCON_ENABLE | USB_EPCON_CLEARNAK;
+
+ return 0;
+}
+
+static void usbIRQHandler(uint32_t token) {
+
+ // we need to mask because GINTSTS is set for a particular interrupt even if it's masked in GINTMSK (GINTMSK just prevents an interrupt being generated)
+ uint32_t status = GET_REG(USB + GINTSTS) & GET_REG(USB + GINTMSK);
+ int process = FALSE;
+
+ //uartPrintf("<begin interrupt: %x>\r\n", status);
+
+ if(status) {
+ process = TRUE;
+ }
+
+ while(process) {
+ if((status & GINTMSK_OTG) == GINTMSK_OTG) {
+ // acknowledge OTG interrupt (these bits are all R_SS_WC which means Write Clear, a write of 1 clears the bits)
+ SET_REG(USB + GOTGINT, GET_REG(USB + GOTGINT));
+
+ // acknowledge interrupt (this bit is actually RO, but should've been cleared when we cleared GOTGINT. Still, iBoot pokes it as if it was WC, so we will too)
+ SET_REG(USB + GINTSTS, GINTMSK_OTG);
+
+ process = TRUE;
+ } else {
+ // we only care about OTG
+ process = FALSE;
+ }
+
+ if((status & GINTMSK_RESET) == GINTMSK_RESET) {
+ if(usb_state < USBError) {
+ //bufferPrintf("usb: reset detected\r\n");
+ change_state(USBPowered);
+ }
+
+ int retval = resetUSB();
+
+ SET_REG(USB + GINTSTS, GINTMSK_RESET);
+
+ if(retval) {
+ //bufferPrintf("usb: listening for further usb events\r\n");
+ return;
+ }
+
+ process = TRUE;
+ }
+
+ if(((status & GINTMSK_INEP) == GINTMSK_INEP) || ((status & GINTMSK_OEP) == GINTMSK_OEP)) {
+ // aha, got something on one of the endpoints. Now the real fun begins
+
+ // first, let's get the interrupt status of individual endpoints
+ getEndpointInterruptStatuses();
+
+ if(isSetupPhaseDone()) {
+ // recall our earlier receiveControl calls. We now should have 8 bytes of goodness in controlRecvBuffer.
+ USBSetupPacket* setupPacket = (USBSetupPacket*) controlRecvBuffer;
+
+ uint16_t length;
+ uint32_t totalLength;
+ USBStringDescriptor* strDesc;
+ if(USBSetupPacketRequestTypeType(setupPacket->bmRequestType) != USBSetupPacketVendor) {
+ switch(setupPacket->bRequest) {
+ case USB_GET_DESCRIPTOR:
+ length = setupPacket->wLength;
+ // descriptor type is high, descriptor index is low
+ int stall = FALSE;
+ switch(setupPacket->wValue >> 8) {
+ case USBDeviceDescriptorType:
+ if(length > sizeof(USBDeviceDescriptor))
+ length = sizeof(USBDeviceDescriptor);
+
+ memcpy(controlSendBuffer, usb_get_device_descriptor(), length);
+ break;
+ case USBConfigurationDescriptorType:
+ // hopefully SET_ADDRESS was received beforehand to set the speed
+ totalLength = getConfigurationTree(setupPacket->wValue & 0xFF, usb_speed, controlSendBuffer);
+ if(length > totalLength)
+ length = totalLength;
+ break;
+ case USBStringDescriptorType:
+ strDesc = usb_get_string_descriptor(setupPacket->wValue & 0xFF);
+ if(length > strDesc->bLength)
+ length = strDesc->bLength;
+ memcpy(controlSendBuffer, strDesc, length);
+ break;
+ case USBDeviceQualifierDescriptorType:
+ if(length > sizeof(USBDeviceQualifierDescriptor))
+ length = sizeof(USBDeviceQualifierDescriptor);
+
+ memcpy(controlSendBuffer, usb_get_device_qualifier_descriptor(), length);
+ break;
+ default:
+ //bufferPrintf("Unknown descriptor request: %d\r\n", setupPacket->wValue >> 8);
+ stall = TRUE;
+ }
+
+ if(usb_state < USBError) {
+ if(stall)
+ stallControl();
+ else
+ sendControl(controlSendBuffer, length);
+ }
+
+ break;
+
+ case USB_SET_ADDRESS:
+ usb_speed = DSTS_GET_SPEED(GET_REG(USB + DSTS));
+ usb_max_packet_size = packetsizeFromSpeed(usb_speed);
+ SET_REG(USB + DCFG, (GET_REG(USB + DCFG) & ~DCFG_DEVICEADDRMSK)
+ | ((setupPacket->wValue & DCFG_DEVICEADDR_UNSHIFTED_MASK) << DCFG_DEVICEADDR_SHIFT));
+
+ // send an acknowledgement
+ sendControl(controlSendBuffer, 0);
+
+ if(usb_state < USBError) {
+ change_state(USBAddress);
+ }
+ break;
+
+ case USB_SET_INTERFACE:
+ // send an acknowledgement
+ sendControl(controlSendBuffer, 0);
+ break;
+
+ case USB_GET_STATUS:
+ // FIXME: iBoot doesn't really care about this status
+ *((uint16_t*) controlSendBuffer) = 0;
+ sendControl(controlSendBuffer, sizeof(uint16_t));
+ break;
+
+ case USB_GET_CONFIGURATION:
+ // FIXME: iBoot just puts out a debug message on console for this request.
+ break;
+
+ case USB_SET_CONFIGURATION:
+ setConfiguration(0);
+ // send an acknowledgment
+ sendControl(controlSendBuffer, 0);
+
+ if(usb_state < USBError) {
+ change_state(USBConfigured);
+ startHandler();
+ }
+ break;
+ default:
+ if(usb_state < USBError) {
+ change_state(USBUnknownRequest);
+ }
+ }
+
+ // get the next SETUP packet
+ receiveControl(controlRecvBuffer, sizeof(USBSetupPacket));
+ }
+ } else {
+ //uartPrintf("\t<begin callEndpointHandlers>\r\n");
+ callEndpointHandlers();
+ //uartPrintf("\t<end callEndpointHandlers>\r\n");
+ }
+
+ process = TRUE;
+ }
+
+ if((status & GINTMSK_SOF) == GINTMSK_SOF) {
+ SET_REG(USB + GINTSTS, GINTMSK_SOF);
+ process = TRUE;
+ }
+
+ if((status & GINTMSK_SUSPEND) == GINTMSK_SUSPEND) {
+ SET_REG(USB + GINTSTS, GINTMSK_SUSPEND);
+ process = TRUE;
+ }
+
+ status = GET_REG(USB + GINTSTS) & GET_REG(USB + GINTMSK);
+ }
+
+ //uartPrintf("<end interrupt>\r\n");
+
+}
+
+static void create_descriptors() {
+ if(configurations == NULL) {
+ deviceDescriptor.bLength = sizeof(USBDeviceDescriptor);
+ deviceDescriptor.bDescriptorType = USBDeviceDescriptorType;
+ deviceDescriptor.bcdUSB = USB_2_0;
+ deviceDescriptor.bDeviceClass = 0;
+ deviceDescriptor.bDeviceSubClass = 0;
+ deviceDescriptor.bDeviceProtocol = 0;
+ deviceDescriptor.bMaxPacketSize = USB_MAX_PACKETSIZE;
+ deviceDescriptor.idVendor = 0x525;
+ deviceDescriptor.idProduct = PRODUCT_IPHONE;
+ deviceDescriptor.bcdDevice = DEVICE_IPHONE;
+ deviceDescriptor.iManufacturer = addStringDescriptor("Apple Inc.");
+ deviceDescriptor.iProduct = addStringDescriptor("Apple Mobile Device (OpenIBoot Mode)");
+ deviceDescriptor.iSerialNumber = addStringDescriptor("");
+ deviceDescriptor.bNumConfigurations = 0;
+
+ deviceQualifierDescriptor.bDescriptorType = USBDeviceDescriptorType;
+ deviceQualifierDescriptor.bcdUSB = USB_2_0;
+ deviceQualifierDescriptor.bDeviceClass = 0;
+ deviceQualifierDescriptor.bDeviceSubClass = 0;
+ deviceQualifierDescriptor.bDeviceProtocol = 0;
+ deviceDescriptor.bMaxPacketSize = USB_MAX_PACKETSIZE;
+ deviceDescriptor.bNumConfigurations = 0;
+
+ addConfiguration(1, addStringDescriptor("OpenIBoot Mode Configuration"), 0, 0, 500);
+ }
+}
+
+USBDeviceDescriptor* usb_get_device_descriptor() {
+ create_descriptors();
+ return &deviceDescriptor;
+}
+
+USBDeviceQualifierDescriptor* usb_get_device_qualifier_descriptor() {
+ create_descriptors();
+ return &deviceQualifierDescriptor;
+}
+
+static void setConfiguration(int i) {
+ int8_t j;
+ for(j = 0; j < configurations[i].descriptor.bNumInterfaces; j++) {
+ int8_t k;
+ for(k = 0; k < configurations[i].interfaces[j].descriptor.bNumEndpoints; k++) {
+ int endpoint = configurations[i].interfaces[j].endpointDescriptors[k].bEndpointAddress & 0x3;
+ if((configurations[i].interfaces[j].endpointDescriptors[k].bEndpointAddress & (0x1 << 7)) == (0x1 << 7)) {
+ InEPRegs[endpoint].control = InEPRegs[endpoint].control | DCTL_SETD0PID;
+ } else {
+ OutEPRegs[endpoint].control = OutEPRegs[endpoint].control | DCTL_SETD0PID;
+ }
+ }
+ }
+}
+
+static uint32_t getConfigurationTree(int i, uint8_t speed_id, void* buffer) {
+ uint8_t *buf = (uint8_t*) buffer;
+ uint32_t pos = 0;
+
+ if(configurations == NULL) {
+ return 0;
+ }
+
+ memcpy(buf + pos, usb_get_configuration_descriptor(i, speed_id), sizeof(USBConfigurationDescriptor));
+ pos += sizeof(USBConfigurationDescriptor);
+
+ int8_t j;
+ for(j = 0; j < configurations[i].descriptor.bNumInterfaces; j++) {
+ memcpy(buf + pos, &configurations[i].interfaces[j].descriptor, sizeof(USBInterfaceDescriptor));
+ pos += sizeof(USBInterfaceDescriptor);
+ int8_t k;
+ for(k = 0; k < configurations[i].interfaces[j].descriptor.bNumEndpoints; k++) {
+ memcpy(buf + pos, &configurations[i].interfaces[j].endpointDescriptors[k], sizeof(USBEndpointDescriptor));
+ pos += sizeof(USBEndpointDescriptor);
+ }
+ }
+
+ return pos;
+}
+
+USBConfigurationDescriptor* usb_get_configuration_descriptor(int index, uint8_t speed_id) {
+ if(index == 0 && configurations[0].interfaces == NULL) {
+ USBInterface* interface = addInterfaceDescriptor(&configurations[0], 0, 0,
+ OPENIBOOT_INTERFACE_CLASS, OPENIBOOT_INTERFACE_SUBCLASS, OPENIBOOT_INTERFACE_PROTOCOL, addStringDescriptor("IF0"));
+
+ enumerateHandler(interface);
+ endConfiguration(&configurations[0]);
+ }
+
+ return &configurations[index].descriptor;
+}
+
+void usb_add_endpoint(USBInterface* interface, int endpoint, USBDirection direction, USBTransferType transferType) {
+ if(transferType == USBInterrupt) {
+ if(usb_speed == USB_HIGHSPEED)
+ addEndpointDescriptor(interface, endpoint, direction, transferType, USBNoSynchronization, USBDataEndpoint, packetsizeFromSpeed(usb_speed), 9);
+ else
+ addEndpointDescriptor(interface, endpoint, direction, transferType, USBNoSynchronization, USBDataEndpoint, packetsizeFromSpeed(usb_speed), 32);
+ } else {
+ addEndpointDescriptor(interface, endpoint, direction, transferType, USBNoSynchronization, USBDataEndpoint, packetsizeFromSpeed(usb_speed), 0);
+ }
+}
+
+static void initializeDescriptors() {
+ numStringDescriptors = 0;
+ stringDescriptors = NULL;
+ configurations = NULL;
+ firstStringDescriptor = NULL;
+ firstStringDescriptor = (USBFirstStringDescriptor*) malloc(sizeof(USBFirstStringDescriptor) + (sizeof(uint16_t) * 1));
+ firstStringDescriptor->bLength = sizeof(USBFirstStringDescriptor) + (sizeof(uint16_t) * 1);
+ firstStringDescriptor->bDescriptorType = USBStringDescriptorType;
+ firstStringDescriptor->wLANGID[0] = USB_LANGID_ENGLISH_US;
+}
+
+static void releaseConfigurations() {
+ if(configurations == NULL) {
+ return;
+ }
+
+ int8_t i;
+ for(i = 0; i < deviceDescriptor.bNumConfigurations; i++) {
+ int8_t j;
+ for(j = 0; j < configurations[i].descriptor.bNumInterfaces; j++) {
+ free(configurations[i].interfaces[j].endpointDescriptors);
+ }
+ free(configurations[i].interfaces);
+ }
+
+ free(configurations);
+ deviceDescriptor.bNumConfigurations = 0;
+ configurations = NULL;
+}
+
+static uint8_t addConfiguration(uint8_t bConfigurationValue, uint8_t iConfiguration, uint8_t selfPowered, uint8_t remoteWakeup, uint16_t maxPower) {
+ uint8_t newIndex = deviceDescriptor.bNumConfigurations;
+ deviceDescriptor.bNumConfigurations++;
+ deviceQualifierDescriptor.bNumConfigurations++;
+
+ configurations = (USBConfiguration*) realloc(configurations, sizeof(USBConfiguration) * deviceDescriptor.bNumConfigurations);
+ configurations[newIndex].descriptor.bLength = sizeof(USBConfigurationDescriptor);
+ configurations[newIndex].descriptor.bDescriptorType = USBConfigurationDescriptorType;
+ configurations[newIndex].descriptor.wTotalLength = 0;
+ configurations[newIndex].descriptor.bNumInterfaces = 0;
+ configurations[newIndex].descriptor.bConfigurationValue = bConfigurationValue;
+ configurations[newIndex].descriptor.iConfiguration = iConfiguration;
+ configurations[newIndex].descriptor.bmAttributes = ((0x1) << 7) | ((selfPowered & 0x1) << 6) | ((remoteWakeup & 0x1) << 5);
+ configurations[newIndex].descriptor.bMaxPower = maxPower / 2;
+ configurations[newIndex].interfaces = NULL;
+
+ return newIndex;
+}
+
+static void endConfiguration(USBConfiguration* configuration) {
+ configuration->descriptor.wTotalLength = sizeof(USBConfigurationDescriptor);
+
+ int i;
+ for(i = 0; i < configurations->descriptor.bNumInterfaces; i++) {
+ configuration->descriptor.wTotalLength += sizeof(USBInterfaceDescriptor) + (configuration->interfaces[i].descriptor.bNumEndpoints * sizeof(USBEndpointDescriptor));
+ }
+}
+
+static USBInterface* addInterfaceDescriptor(USBConfiguration* configuration, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bInterfaceClass, uint8_t bInterfaceSubClass, uint8_t bInterfaceProtocol, uint8_t iInterface) {
+ uint8_t newIndex = configuration->descriptor.bNumInterfaces;
+ configuration->descriptor.bNumInterfaces++;
+
+ configuration->interfaces = (USBInterface*) realloc(configuration->interfaces, sizeof(USBInterface) * configuration->descriptor.bNumInterfaces);
+ configuration->interfaces[newIndex].descriptor.bLength = sizeof(USBInterfaceDescriptor);
+ configuration->interfaces[newIndex].descriptor.bDescriptorType = USBInterfaceDescriptorType;
+ configuration->interfaces[newIndex].descriptor.bInterfaceNumber = bInterfaceNumber;
+ configuration->interfaces[newIndex].descriptor.bAlternateSetting = bAlternateSetting;
+ configuration->interfaces[newIndex].descriptor.bInterfaceClass = bInterfaceClass;
+ configuration->interfaces[newIndex].descriptor.bInterfaceSubClass = bInterfaceSubClass;
+ configuration->interfaces[newIndex].descriptor.bInterfaceProtocol = bInterfaceProtocol;
+ configuration->interfaces[newIndex].descriptor.iInterface = iInterface;
+ configuration->interfaces[newIndex].descriptor.bNumEndpoints = 0;
+ configuration->interfaces[newIndex].endpointDescriptors = NULL;
+
+ return &configuration->interfaces[newIndex];
+}
+
+static uint8_t addEndpointDescriptor(USBInterface* interface, uint8_t endpoint, USBDirection direction, USBTransferType transferType, USBSynchronisationType syncType, USBUsageType usageType, uint16_t wMaxPacketSize, uint8_t bInterval) {
+ if(direction > 2)
+ return -1;
+
+ uint8_t newIndex = interface->descriptor.bNumEndpoints;
+ interface->descriptor.bNumEndpoints++;
+
+ interface->endpointDescriptors = (USBEndpointDescriptor*) realloc(interface->endpointDescriptors, sizeof(USBEndpointDescriptor) * interface->descriptor.bNumEndpoints);
+ interface->endpointDescriptors[newIndex].bLength = sizeof(USBEndpointDescriptor);
+ interface->endpointDescriptors[newIndex].bDescriptorType = USBEndpointDescriptorType;
+ interface->endpointDescriptors[newIndex].bEndpointAddress = (endpoint & 0xF) | ((direction & 0x1) << 7); // see USB specs for the bitfield spec
+ interface->endpointDescriptors[newIndex].bmAttributes = (transferType & 0x3) | ((syncType & 0x3) << 2) | ((usageType & 0x3) << 4);
+ interface->endpointDescriptors[newIndex].wMaxPacketSize = wMaxPacketSize;
+ interface->endpointDescriptors[newIndex].bInterval = bInterval;
+
+ return newIndex;
+}
+
+static uint8_t addStringDescriptor(const char* descriptorString) {
+ uint8_t newIndex = numStringDescriptors;
+ numStringDescriptors++;
+
+ stringDescriptors = (USBStringDescriptor**) realloc(stringDescriptors, sizeof(USBStringDescriptor*) * numStringDescriptors);
+
+ int sLen = strlen(descriptorString);
+ stringDescriptors[newIndex] = (USBStringDescriptor*) malloc(sizeof(USBStringDescriptor) + sLen * 2);
+ stringDescriptors[newIndex]->bLength = sizeof(USBStringDescriptor) + sLen * 2;
+ stringDescriptors[newIndex]->bDescriptorType = USBStringDescriptorType;
+ uint16_t* string = (uint16_t*) stringDescriptors[newIndex]->bString;
+ int i;
+ for(i = 0; i < sLen; i++) {
+ string[i] = descriptorString[i];
+ }
+
+ return (newIndex + 1);
+}
+
+USBStringDescriptor* usb_get_string_descriptor(int index) {
+ if(index == 0) {
+ return (USBStringDescriptor*) firstStringDescriptor;
+ } else {
+ return stringDescriptors[index - 1];
+ }
+}
+
+static void releaseStringDescriptors() {
+ int8_t i;
+
+ if(stringDescriptors == NULL) {
+ return;
+ }
+
+ for(i = 0; i < numStringDescriptors; i++) {
+ free(stringDescriptors[i]);
+ }
+
+ free(stringDescriptors);
+
+ numStringDescriptors = 0;
+ stringDescriptors = NULL;
+}
+
+static uint16_t packetsizeFromSpeed(uint8_t speed_id) {
+ switch(speed_id) {
+ case USB_HIGHSPEED:
+ return 512;
+ case USB_FULLSPEED:
+ case USB_FULLSPEED_48_MHZ:
+ return 64;
+ case USB_LOWSPEED:
+ return 32;
+ default:
+ return -1;
+ }
+}
+
+int usb_install_ep_handler(int endpoint, USBDirection direction, USBEndpointHandler handler, uint32_t token) {
+ if(endpoint >= USB_NUM_ENDPOINTS) {
+ return -1;
+ }
+
+ if(endpoint_directions[endpoint] != direction && endpoint_directions[endpoint] != USBBiDir) {
+ return -1; // that endpoint can't handle this kind of direction
+ }
+
+ if(direction == USBIn) {
+ endpoint_handlers[endpoint].in.handler = handler;
+ endpoint_handlers[endpoint].in.token = token;
+ } else if(direction == USBOut) {
+ endpoint_handlers[endpoint].out.handler = handler;
+ endpoint_handlers[endpoint].out.token = token;
+ } else {
+ return -1; // can only register IN or OUt directions
+ }
+
+ return 0;
+}
+
+int usb_shutdown() {
+ power_ctrl(POWER_USB, ON);
+ power_ctrl(USB_OTGCLOCKGATE, ON);
+ power_ctrl(USB_PHYCLOCKGATE, ON);
+
+ SET_REG(USB + USB_ONOFF, GET_REG(USB + USB_ONOFF) | USB_ONOFF_OFF); // reset link
+ SET_REG(USB_PHY + OPHYPWR, OPHYPWR_FORCESUSPEND | OPHYPWR_PLLPOWERDOWN
+ | OPHYPWR_XOPOWERDOWN | OPHYPWR_ANALOGPOWERDOWN | OPHYPWR_UNKNOWNPOWERDOWN); // power down phy
+
+ SET_REG(USB_PHY + ORSTCON, ORSTCON_PHYSWRESET | ORSTCON_LINKSWRESET | ORSTCON_PHYLINKSWRESET); // reset phy/link
+
+ udelay(USB_RESET_DELAYUS); // wait a millisecond for the changes to stick
+
+ power_ctrl(USB_OTGCLOCKGATE, OFF);
+ power_ctrl(USB_PHYCLOCKGATE, OFF);
+ power_ctrl(POWER_USB, OFF);
+
+ releaseConfigurations();
+ releaseStringDescriptors();
+
+ return 0;
+}
+
+static void change_state(USBState new_state) {
+ //bufferPrintf("USB state change: %d -> %d\r\n", usb_state, new_state);
+ usb_state = new_state;
+ if(usb_state == USBConfigured) {
+ // TODO: set to host powered
+ }
+}
+
+
+static RingBuffer* createRingBuffer(int size) {
+ RingBuffer* buffer;
+ buffer = (RingBuffer*) malloc(sizeof(RingBuffer));
+ buffer->bufferStart = (int8_t*) IOMallocAligned(size, DMA_ALIGN);
+ buffer->bufferEnd = buffer->bufferStart + size;
+ buffer->size = size;
+ buffer->count = 0;
+ buffer->readPtr = buffer->bufferStart;
+ buffer->writePtr = buffer->bufferStart;
+
+ return buffer;
+}
+
+static int8_t ringBufferDequeue(RingBuffer* buffer) {
+ EnterCriticalSection();
+ if(buffer->count == 0) {
+ LeaveCriticalSection();
+ return -1;
+ }
+
+ int8_t value = *buffer->readPtr;
+ buffer->readPtr++;
+ buffer->count--;
+
+ if(buffer->readPtr == buffer->bufferEnd) {
+ buffer->readPtr = buffer->bufferStart;
+ }
+
+ //uartPrintf("queue(dequeue): %d %x %x %x %x\r\n", buffer->count, buffer->readPtr, buffer->writePtr, buffer->bufferStart, buffer->bufferEnd);
+ LeaveCriticalSection();
+ return value;
+}
+
+static int8_t ringBufferEnqueue(RingBuffer* buffer, uint8_t value) {
+ EnterCriticalSection();
+ if(buffer->count == buffer->size) {
+ LeaveCriticalSection();
+ return -1;
+ }
+
+ *buffer->writePtr = value;
+ buffer->writePtr++;
+ buffer->count++;
+
+ if(buffer->writePtr == buffer->bufferEnd) {
+ buffer->writePtr = buffer->bufferStart;
+ }
+
+ //uartPrintf("queue(enqueue): %d %x %x %x %x\r\n", buffer->count, buffer->readPtr, buffer->writePtr, buffer->bufferStart, buffer->bufferEnd);
+ LeaveCriticalSection();
+
+ return value;
+}
+
+USBSpeed usb_get_speed() {
+ switch(usb_speed) {
+ case USB_HIGHSPEED:
+ return USBHighSpeed;
+ case USB_FULLSPEED:
+ case USB_FULLSPEED_48_MHZ:
+ return USBFullSpeed;
+ case USB_LOWSPEED:
+ return USBLowSpeed;
+ }
+
+ return USBLowSpeed;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.