diff options
author | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
---|---|---|
committer | Denys Dmytriyenko <denis@denix.org> | 2009-03-17 14:32:59 -0400 |
commit | 709c4d66e0b107ca606941b988bad717c0b45d9b (patch) | |
tree | 37ee08b1eb308f3b2b6426d5793545c38396b838 /recipes/linux/opensimpad | |
parent | fa6cd5a3b993f16c27de4ff82b42684516d433ba (diff) |
rename packages/ to recipes/ per earlier agreement
See links below for more details:
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21326
http://thread.gmane.org/gmane.comp.handhelds.openembedded/21816
Signed-off-by: Denys Dmytriyenko <denis@denix.org>
Acked-by: Mike Westerhof <mwester@dls.net>
Acked-by: Philip Balister <philip@balister.org>
Acked-by: Khem Raj <raj.khem@gmail.com>
Acked-by: Marcin Juszkiewicz <hrw@openembedded.org>
Acked-by: Koen Kooi <koen@openembedded.org>
Acked-by: Frans Meulenbroeks <fransmeulenbroeks@gmail.com>
Diffstat (limited to 'recipes/linux/opensimpad')
-rw-r--r-- | recipes/linux/opensimpad/disable-pcmcia-probe.patch | 17 | ||||
-rw-r--r-- | recipes/linux/opensimpad/mkdep.patch | 16 | ||||
-rw-r--r-- | recipes/linux/opensimpad/mmc-spi.patch | 885 | ||||
-rw-r--r-- | recipes/linux/opensimpad/mppe-20040216.patch | 1225 | ||||
-rw-r--r-- | recipes/linux/opensimpad/sa1100-usb-tcl1.patch | 216 | ||||
-rw-r--r-- | recipes/linux/opensimpad/simpad-backlight-if.patch | 102 | ||||
-rw-r--r-- | recipes/linux/opensimpad/simpad-proc-sys-board.patch | 317 | ||||
-rw-r--r-- | recipes/linux/opensimpad/simpad-serial.patch | 267 | ||||
-rw-r--r-- | recipes/linux/opensimpad/simpad-switches-input.patch | 131 | ||||
-rw-r--r-- | recipes/linux/opensimpad/simpad-switches-input2.patch | 41 | ||||
-rw-r--r-- | recipes/linux/opensimpad/simpad-ts-noninput.patch | 16 | ||||
-rw-r--r-- | recipes/linux/opensimpad/sound-volume-reversed.patch | 16 | ||||
-rw-r--r-- | recipes/linux/opensimpad/support-128mb-ram.patch | 35 |
13 files changed, 3284 insertions, 0 deletions
diff --git a/recipes/linux/opensimpad/disable-pcmcia-probe.patch b/recipes/linux/opensimpad/disable-pcmcia-probe.patch new file mode 100644 index 0000000000..0ab9439982 --- /dev/null +++ b/recipes/linux/opensimpad/disable-pcmcia-probe.patch @@ -0,0 +1,17 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/drivers/pcmcia/Config.in~disable-pcmcia-probe ++++ linux-2.4.27/drivers/pcmcia/Config.in +@@ -15,9 +15,6 @@ + tristate 'PCMCIA/CardBus support' CONFIG_PCMCIA + if [ "$CONFIG_PCMCIA" != "n" ]; then + # yes, I really mean the following... +- if [ "$CONFIG_ISA" = "y" -o "$CONFIG_ARCH_SA1100" = "y" ]; then +- define_bool CONFIG_PCMCIA_PROBE y +- fi + if [ "$CONFIG_PCI" != "n" ]; then + bool ' CardBus support' CONFIG_CARDBUS + fi diff --git a/recipes/linux/opensimpad/mkdep.patch b/recipes/linux/opensimpad/mkdep.patch new file mode 100644 index 0000000000..6dc51403b2 --- /dev/null +++ b/recipes/linux/opensimpad/mkdep.patch @@ -0,0 +1,16 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/Makefile~mkdep ++++ linux-2.4.27/Makefile +@@ -501,7 +501,7 @@ + ifdef CONFIG_MODVERSIONS + $(MAKE) update-modverfile + endif +- scripts/mkdep -- `find $(FINDHPATH) \( -name SCCS -o -name .svn \) -prune -o -follow -name \*.h ! -name modversions.h -print` > .hdepend ++ $(foreach, dir, $(FINDHPATH), scripts/mkdep -- `find $(dir) -name SCCS -prune -o -follow -name \*.h ! -name modversions.h -print` >> .hdepend) + scripts/mkdep -- init/*.c > .depend + + ifdef CONFIG_MODVERSIONS diff --git a/recipes/linux/opensimpad/mmc-spi.patch b/recipes/linux/opensimpad/mmc-spi.patch new file mode 100644 index 0000000000..1841b45fbd --- /dev/null +++ b/recipes/linux/opensimpad/mmc-spi.patch @@ -0,0 +1,885 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- /dev/null ++++ linux-2.4.27/drivers/block/mmc.c +@@ -0,0 +1,857 @@ ++/* ++ * Copyright (c) Clément Ballabriga, 2005 - GPL ++ * Copyright (c) Guylhem Aznar, 2005 - GPL ++ * ++ * Please check http://externe.net/zaurus/simpad-bluetooth reference design first. ++ * ++ * Based on Madsuk/Rohde work on a MMC driver for the WRT54G. ++ * ++ * This is an ugly hack of a driver. I am surprised if it ever works! ++ * So please use a real driver or contribute one to the 2.4/2.6 mmc framework ++ */ ++ ++#include <linux/stddef.h> ++#include <linux/delay.h> ++#include <linux/timer.h> ++#include <linux/module.h> ++#include <linux/mm.h> ++#include <linux/init.h> ++#include <linux/fs.h> ++#include <linux/blkpg.h> ++#include <linux/hdreg.h> ++#include <linux/major.h> ++ ++#include <asm/hardware.h> ++#include <asm/uaccess.h> ++#include <asm/io.h> ++ ++/* ++ * ******************************************************************* ++ * ++ * This is the only configurable part. ++ * ++ * ******************************************************************* ++ * ++ */ ++ ++// #define DEBUG 1 ++ ++#define DEVICE_NAME "mmc" ++#define DEVICE_NR(device) (MINOR(device)) ++#define DEVICE_ON(device) ++#define DEVICE_OFF(device) ++#define MAJOR_NR 121 ++ ++/* Let that include where it is or compilation fails on INIT_REQUEST/CURRENT */ ++ ++#include <linux/blk.h> ++ ++MODULE_AUTHOR("Guylhem Aznar <mmc-driver @externe.net>"); ++MODULE_DESCRIPTION("Driver for MMC/SD-Cards in SPI mode by GPIO"); ++MODULE_SUPPORTED_DEVICE("Simpad"); ++MODULE_LICENSE("GPL"); ++ ++/* Registers should be architecture independant - but it's not ! */ ++ ++#define MAP_START 0x90040000 ++#define MAP_SIZE 0x00001000 ++ ++#define MY_GPLR 0 ++#define MY_GPDR 1 ++#define MY_GPSR 2 ++#define MY_GPCR 3 ++#define MY_GRER 4 ++#define MY_GFER 5 ++#define MY_GEDR 6 ++#define MY_GAFR 7 ++ ++/* ++ * If you are using different GPIOs in your hardware hack, you must ++ * first make sure they are unused for other functions and then ++ * configure them here. ++ * ++ * On the simpad I use spare pins from the UART1 (internal serial port): ++ * - DCD (in) : GPIO 23 : DO ++ * - DTR (out) : GPIO 07 : CS ++ * - RI (in) : GPIO 19 : CLK ++ * - DSR (in) : GPIO 06 : DI ++ * ++ * Don't worry about in/out original function - the GPIOs will be ++ * reprogrammed. ++ */ ++ ++#define GPIO_SD_DO 23 ++#define GPIO_SD_CS 7 ++#define GPIO_SD_CLK 19 ++#define GPIO_SD_DI 6 ++ ++/* ++ * ******************************************************************* ++ * ++ * Do not change anything below ! ++ * ++ * ******************************************************************* ++ * ++ */ ++ ++ ++/* GPIO states */ ++#define LOW 0 ++#define HIGH 1 ++ ++#define INPUT 0 ++#define OUTPUT 1 ++ ++#define PRESENT 1 ++#define ABSENT 0 ++ ++typedef unsigned int uint32; ++typedef unsigned long u32_t; ++typedef unsigned short u16_t; ++typedef unsigned char u8_t; ++ ++/* we have only one device */ ++static int hd_sizes[1 << 6]; ++static int hd_blocksizes[1 << 6]; ++static int hd_hardsectsizes[1 << 6]; ++static int hd_maxsect[1 << 6]; ++static struct hd_struct hd[1 << 6]; ++ ++static struct timer_list mmc_timer; ++ ++/* start with no card */ ++static int mmc_media_detect = 0; ++static int mmc_media_changed = 1; ++ ++extern struct gendisk hd_gendisk; ++ ++/* Use only one global device */ ++typedef struct gpio_s gpio_t; ++struct gpio_s { ++ volatile u32_t *base; ++}; ++ ++static gpio_t gp = { ++ (void *) io_p2v(MAP_START) ++}; ++ ++/* ++ * ******************************************************************* ++ * ++ * Begin GPIO hardware access functions. ++ * ++ * ******************************************************************* ++ * ++ */ ++ ++gpio_t *gpio_open(void) ++{ ++ static gpio_t tmp; ++ tmp.base = (void *) io_p2v(MAP_START); ++ return (&tmp); ++} ++ ++void gpio_setdir(gpio_t * g, int num, int dir) ++{ ++ if (dir == 1) { ++ g->base[MY_GPDR] |= (1 << num); ++ } else { ++ g->base[MY_GPDR] &= ~(1 << num); ++ ++ } ++} ++ ++void gpio_setalt(gpio_t * g, int num, int alt) ++{ ++ if (alt == 1) { ++ g->base[MY_GAFR] |= (1 << num); ++ } else { ++ g->base[MY_GAFR] &= ~(1 << num); ++ } ++} ++ ++int gpio_getdir(gpio_t * g, int num) ++{ ++ return ((g->base[MY_GPDR] & (1 << num)) ? 1 : 0); ++} ++ ++int gpio_getalt(gpio_t * g, int num) ++{ ++ return ((g->base[MY_GAFR] & (1 << num)) ? 1 : 0); ++} ++ ++static int gpio_read(gpio_t * g, int num) ++{ ++ int what; ++ ++ what=(g->base[MY_GPLR] & (1 << num)) ? 1 : 0; ++ ++#ifdef DEBUG ++ if (num == GPIO_SD_DO) { ++ printk ("GPIO_SD_DO read: %u\n", what); ++ } ++#endif ++ return (what); ++} ++ ++static int gpio_write(gpio_t * g, int num, int val) ++{ ++#ifdef DEBUG ++ int check; ++#endif ++ ++ if (val == 1) { ++ g->base[MY_GPSR] = 1 << num; ++ } else { ++ g->base[MY_GPCR] = 1 << num; ++ } ++#ifdef DEBUG ++ check=gpio_read(g,num); ++ if (check != val) ++ { ++ printk ("Error while write to %d: found %d after writing %d\n",num, check, val); ++ return (1); ++ } ++ else return(0); ++#endif ++ ++} ++ ++/* ++ * ******************************************************************* ++ * ++ * Begin SPI hardware access functions. ++ * ++ * ******************************************************************* ++ * ++ */ ++static int mmc_spi_media_detect(void) ++{ ++// FIXME: add card detection/test by SPI ++ ++ return 1; ++} ++ ++static int mmc_spi_hardware_init(void) ++{ ++ /*unsigned char gpio_outen;*/ ++ ++ printk("mmc: GPIO init\n"); ++ ++ /* Now global ++ * gp = gpio_open(); */ ++ ++ /* Cut existing functions */ ++ gpio_setalt(&gp, GPIO_SD_CLK, 0); ++ gpio_setalt(&gp, GPIO_SD_DI, 0); ++ gpio_setalt(&gp, GPIO_SD_DO, 0); ++ gpio_setalt(&gp, GPIO_SD_CS, 0); ++ ++ /* Remap directions */ ++ gpio_setdir(&gp, GPIO_SD_CLK, OUTPUT); ++ gpio_setdir(&gp, GPIO_SD_DI, OUTPUT); ++ gpio_setdir(&gp, GPIO_SD_DO, INPUT); ++ gpio_setdir(&gp, GPIO_SD_CS, OUTPUT); ++ ++ printk("mmc: initialising MMC\n"); ++ ++ /* Start */ ++ gpio_write(&gp, GPIO_SD_CLK, LOW); ++ gpio_write(&gp, GPIO_SD_DI, LOW); ++ gpio_write(&gp, GPIO_SD_CS, LOW); ++ return 0; ++} ++ ++/* return what has been read, write the parameter */ ++ ++static unsigned char mmc_spi_readwrite(unsigned char data_out) ++{ ++ int i; ++ unsigned char result = 0/*, tmp_data = 0*/; ++ ++ for (i = 0; i < 8; i++) { ++ if (data_out & (0x01 << (7 - i))) ++ gpio_write(&gp, GPIO_SD_DI, HIGH); ++ else ++ gpio_write(&gp, GPIO_SD_DI, LOW); ++ ++ gpio_write(&gp, GPIO_SD_CLK, HIGH); ++ ++ result <<= 1; ++ ++ if (gpio_read(&gp, GPIO_SD_DO) == 1) ++ result |= 1; ++ ++ gpio_write(&gp, GPIO_SD_CLK, LOW); ++ } ++ ++ return (result); ++} ++ ++static int mmc_spi_card_init(void) ++{ ++ unsigned char result = 0; ++ short i, j; ++ unsigned long flags; ++ ++ save_flags(flags); ++ cli(); ++ ++ printk("GPIO_SD_CS dir: %u alt: %u\n", gpio_getdir(&gp, GPIO_SD_CS), gpio_getalt(&gp, GPIO_SD_CS)); ++ printk("GPIO_SD_DI dir: %u alt: %u\n", gpio_getdir(&gp, GPIO_SD_DI), gpio_getalt(&gp, GPIO_SD_DI)); ++ printk("GPIO_SD_DO dir: %u alt: %u\n", gpio_getdir(&gp, GPIO_SD_DO), gpio_getalt(&gp, GPIO_SD_DO)); ++ printk("GPIO_SD_CS dir: %u alt: %u\n", gpio_getdir(&gp, GPIO_SD_CLK), gpio_getalt(&gp, GPIO_SD_CLK)); ++ ++ printk("mmc: card init 1/2\n"); ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ for (i = 0; i < 20; i++) ++ mmc_spi_readwrite(0xff); ++ ++ gpio_write(&gp, GPIO_SD_CS, LOW); ++ ++ mmc_spi_readwrite(0x40); ++ for (i = 0; i < 4; i++) ++ mmc_spi_readwrite(0x00); ++ mmc_spi_readwrite(0x95); ++ for (i = 0; i < 8; i++) { ++ result = mmc_spi_readwrite(0xff); ++ if (result == 0x01) ++ break; ++ } ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ mmc_spi_readwrite(0xff); ++ if (result != 0x01) { ++ printk("mmc: card init %d error\n", result); ++ restore_flags(flags); ++ return (1); ++ } ++ ++ printk("mmc: card init 2/2\n"); ++ for (j = 0; j < 10000; j++) { ++ gpio_write(&gp, GPIO_SD_CS, LOW); ++ ++ mmc_spi_readwrite(0x41); ++ for (i = 0; i < 4; i++) ++ mmc_spi_readwrite(0x00); ++ mmc_spi_readwrite(0xff); ++ for (i = 0; i < 8; i++) { ++ result = mmc_spi_readwrite(0xff); ++ if (result == 0x00) ++ break; ++ } ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ mmc_spi_readwrite(0xff); ++ if (result == 0x00) { ++ restore_flags(flags); ++ printk("mmc: card init 3/3\n"); ++ return (0); ++ } ++ } ++ restore_flags(flags); ++ ++ return (2); ++} ++ ++ ++static int mmc_spi_card_config(void) ++{ ++ unsigned char result = 0; ++ short i; ++ unsigned char csd[32]; ++ unsigned int c_size; ++ unsigned int c_size_mult; ++ unsigned int mult; ++ unsigned int read_bl_len; ++ unsigned int blocknr = 0; ++ unsigned int block_len = 0; ++ unsigned int size = 0; ++ ++ gpio_write(&gp, GPIO_SD_CS, LOW); ++ for (i = 0; i < 4; i++) ++ mmc_spi_readwrite(0xff); ++ mmc_spi_readwrite(0x49); ++ for (i = 0; i < 4; i++) ++ mmc_spi_readwrite(0x00); ++ mmc_spi_readwrite(0xff); ++ for (i = 0; i < 8; i++) { ++ result = mmc_spi_readwrite(0xff); ++ if (result == 0x00) ++ break; ++ } ++ if (result != 0x00) { ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ mmc_spi_readwrite(0xff); ++ return (1); ++ } ++ for (i = 0; i < 8; i++) { ++ result = mmc_spi_readwrite(0xff); ++ if (result == 0xfe) ++ break; ++ } ++ if (result != 0xfe) { ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ mmc_spi_readwrite(0xff); ++ return (2); ++ } ++ for (i = 0; i < 16; i++) { ++ result = mmc_spi_readwrite(0xff); ++ csd[i] = result; ++ } ++ for (i = 0; i < 2; i++) { ++ result = mmc_spi_readwrite(0xff); ++ } ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ mmc_spi_readwrite(0xff); ++ if (result == 0x00) ++ return (3); ++ ++ c_size = csd[8] + csd[7] * 256 + (csd[6] & 0x03) * 256 * 256; ++ c_size >>= 6; ++ c_size_mult = csd[10] + (csd[9] & 0x03) * 256; ++ c_size_mult >>= 7; ++ read_bl_len = csd[5] & 0x0f; ++ mult = 1; ++ mult <<= c_size_mult + 2; ++ blocknr = (c_size + 1) * mult; ++ block_len = 1; ++ block_len <<= read_bl_len; ++ size = block_len * blocknr; ++ size >>= 10; ++ ++ for (i = 0; i < (1 << 6); i++) { ++ hd_blocksizes[i] = 1024; ++ hd_hardsectsizes[i] = block_len; ++ hd_maxsect[i] = 256; ++ } ++ hd_sizes[0] = size; ++ hd[0].nr_sects = blocknr; ++ ++ ++ printk("Size = %d, hardsectsize = %d, sectors = %d\n", ++ size, block_len, blocknr); ++ ++ return 0; ++} ++ ++ ++/* ++ * ******************************************************************* ++ * ++ * End of SPI hardware access functions. ++ * ++ * ******************************************************************* ++ */ ++ ++ ++static int mmc_write_block(unsigned int dest_addr, unsigned char *data) ++{ ++ unsigned int address; ++ unsigned char result = 0; ++ unsigned char ab0, ab1, ab2, ab3; ++ int i; ++ ++ address = dest_addr; ++ ++ ab3 = 0xff & (address >> 24); ++ ab2 = 0xff & (address >> 16); ++ ab1 = 0xff & (address >> 8); ++ ab0 = 0xff & address; ++ gpio_write(&gp, GPIO_SD_CS, LOW); ++ for (i = 0; i < 4; i++) ++ mmc_spi_readwrite(0xff); ++ mmc_spi_readwrite(0x58); ++ mmc_spi_readwrite(ab3); /* msb */ ++ mmc_spi_readwrite(ab2); ++ mmc_spi_readwrite(ab1); ++ mmc_spi_readwrite(ab0); /* lsb */ ++ mmc_spi_readwrite(0xff); ++ for (i = 0; i < 8; i++) { ++ result = mmc_spi_readwrite(0xff); ++ if (result == 0x00) ++ break; ++ } ++ if (result != 0x00) { ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ mmc_spi_readwrite(0xff); ++ return (1); ++ } ++ ++ mmc_spi_readwrite(0xfe); ++ for (i = 0; i < 512; i++) ++ mmc_spi_readwrite(data[i]); ++ for (i = 0; i < 2; i++) ++ mmc_spi_readwrite(0xff); ++ ++ for (i = 0; i < 1000000; i++) { ++ result = mmc_spi_readwrite(0xff); ++ if (result == 0xff) ++ break; ++ } ++ if (result != 0xff) { ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ mmc_spi_readwrite(0xff); ++ return (3); ++ } ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ mmc_spi_readwrite(0xff); ++ return (0); ++} ++ ++static int mmc_read_block(unsigned char *data, unsigned int src_addr) ++{ ++ unsigned int address; ++ unsigned char result = 0; ++ unsigned char ab0, ab1, ab2, ab3; ++ int i; ++ ++ address = src_addr; ++ ++ ab3 = 0xff & (address >> 24); ++ ab2 = 0xff & (address >> 16); ++ ab1 = 0xff & (address >> 8); ++ ab0 = 0xff & address; ++ ++ gpio_write(&gp, GPIO_SD_CS, LOW); ++ for (i = 0; i < 4; i++) ++ mmc_spi_readwrite(0xff); ++ mmc_spi_readwrite(0x51); ++ mmc_spi_readwrite(ab3); /* msb */ ++ mmc_spi_readwrite(ab2); ++ mmc_spi_readwrite(ab1); ++ mmc_spi_readwrite(ab0); /* lsb */ ++ ++ mmc_spi_readwrite(0xff); ++ for (i = 0; i < 8; i++) { ++ result = mmc_spi_readwrite(0xff); ++ if (result == 0x00) ++ break; ++ } ++ if (result != 0x00) { ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ mmc_spi_readwrite(0xff); ++ return (1); ++ } ++ for (i = 0; i < 100000; i++) { ++ result = mmc_spi_readwrite(0xff); ++ if (result == 0xfe) ++ break; ++ } ++ if (result != 0xfe) { ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ mmc_spi_readwrite(0xff); ++ return (2); ++ } ++ for (i = 0; i < 512; i++) { ++ result = mmc_spi_readwrite(0xff); ++ data[i] = result; ++ } ++ for (i = 0; i < 2; i++) { ++ result = mmc_spi_readwrite(0xff); ++ } ++ gpio_write(&gp, GPIO_SD_CS, HIGH); ++ mmc_spi_readwrite(0xff); ++ ++ return (0); ++} ++ ++static void mmc_request(request_queue_t * q) ++{ ++ unsigned int mmc_address; ++ unsigned char *buffer_address; ++ int nr_sectors; ++ int i; ++ int cmd; ++ int result, code; ++ ++ (void) q; ++ while (1) { ++ code = 1; // Default is success ++ INIT_REQUEST; ++ mmc_address = ++ (CURRENT->sector + ++ hd[MINOR(CURRENT->rq_dev)].start_sect) * hd_hardsectsizes[0]; ++ buffer_address = CURRENT->buffer; ++ nr_sectors = CURRENT->current_nr_sectors; ++ cmd = CURRENT->cmd; ++ if (((CURRENT->sector + CURRENT->current_nr_sectors + ++ hd[MINOR(CURRENT->rq_dev)].start_sect) > hd[0].nr_sects) ++ || (mmc_media_detect == 0)) { ++ code = 0; ++ } else if (cmd == READ) { ++ spin_unlock_irq(&io_request_lock); ++ for (i = 0; i < nr_sectors; i++) { ++ result = mmc_read_block(buffer_address, mmc_address); ++ if (result != 0) { ++ printk("mmc: error %d in mmc_read_block\n", result); ++ code = 0; ++ break; ++ } else { ++ mmc_address += hd_hardsectsizes[0]; ++ buffer_address += hd_hardsectsizes[0]; ++ } ++ } ++ spin_lock_irq(&io_request_lock); ++ } else if (cmd == WRITE) { ++ spin_unlock_irq(&io_request_lock); ++ for (i = 0; i < nr_sectors; i++) { ++ result = mmc_write_block(mmc_address, buffer_address); ++ if (result != 0) { ++ printk("mmc: error %d in mmc_write_block\n", result); ++ code = 0; ++ break; ++ } else { ++ mmc_address += hd_hardsectsizes[0]; ++ buffer_address += hd_hardsectsizes[0]; ++ } ++ } ++ spin_lock_irq(&io_request_lock); ++ } else { ++ code = 0; ++ } ++ end_request(code); ++ } ++} ++ ++ ++static int mmc_open(struct inode *inode, struct file *filp) ++{ ++ /*int device;*/ ++ (void) filp; ++ mmc_media_detect = mmc_spi_media_detect(); ++ ++ if (mmc_media_detect == 0) ++ return -ENODEV; ++ ++#if defined(MODULE) ++ MOD_INC_USE_COUNT; ++#endif ++ return 0; ++} ++ ++static int mmc_release(struct inode *inode, struct file *filp) ++{ ++ (void) filp; ++ fsync_dev(inode->i_rdev); ++ invalidate_buffers(inode->i_rdev); ++ ++#if defined(MODULE) ++ MOD_DEC_USE_COUNT; ++#endif ++ return 0; ++} ++ ++static int mmc_revalidate(kdev_t dev) ++{ ++ int target, max_p, start, i; ++ ++ mmc_media_detect = mmc_spi_media_detect(); ++ ++ if (mmc_media_detect == 0) ++ return -ENODEV; ++ ++ target = DEVICE_NR(dev); ++ ++ max_p = hd_gendisk.max_p; ++ start = target << 6; ++ for (i = max_p - 1; i >= 0; i--) { ++ int minor = start + i; ++ invalidate_device(MKDEV(MAJOR_NR, minor), 1); ++ hd_gendisk.part[minor].start_sect = 0; ++ hd_gendisk.part[minor].nr_sects = 0; ++ } ++ ++ grok_partitions(&hd_gendisk, target, 1 << 6, hd_sizes[0] * 2); ++ ++ return 0; ++} ++ ++static int mmc_ioctl(struct inode *inode, struct file *filp, ++ unsigned int cmd, unsigned long arg) ++{ ++ if (!inode || !inode->i_rdev) ++ return -EINVAL; ++ ++ switch (cmd) { ++ case BLKGETSIZE: ++ return put_user(hd[MINOR(inode->i_rdev)].nr_sects, ++ (unsigned long *) arg); ++ case BLKGETSIZE64: ++ return put_user((u64) hd[MINOR(inode->i_rdev)]. ++ nr_sects, (u64 *) arg); ++ case BLKRRPART: ++ if (!capable(CAP_SYS_ADMIN)) ++ return -EACCES; ++ ++ return mmc_revalidate(inode->i_rdev); ++ case HDIO_GETGEO: ++ { ++ struct hd_geometry *loc, g; ++ loc = (struct hd_geometry *) arg; ++ if (!loc) ++ return -EINVAL; ++ g.heads = 4; ++ g.sectors = 16; ++ g.cylinders = hd[0].nr_sects / (4 * 16); ++ g.start = hd[MINOR(inode->i_rdev)].start_sect; ++ return copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0; ++ } ++ default: ++ return blk_ioctl(inode->i_rdev, cmd, arg); ++ } ++} ++ ++ ++/* ++static int mmc_check_media_change(kdev_t dev) ++{ ++ (void) dev; ++ if (mmc_media_changed == 1) { ++ mmc_media_changed = 0; ++ return 1; ++ } else ++ return 0; ++} ++*/ ++ ++static struct block_device_operations mmc_bdops = { ++ open:mmc_open, ++ release:mmc_release, ++ ioctl:mmc_ioctl, ++/* FIXME: add media change support ++ * check_media_change: mmc_check_media_change, ++ * revalidate: mmc_revalidate, ++ */ ++}; ++ ++static struct gendisk hd_gendisk = { ++ major:MAJOR_NR, ++ major_name:DEVICE_NAME, ++ minor_shift:6, ++ max_p:1 << 6, ++ part:hd, ++ sizes:hd_sizes, ++ fops:&mmc_bdops, ++}; ++ ++static int mmc_init(void) ++{ ++ int result; ++ ++ result = mmc_spi_hardware_init(); ++ ++ if (result != 0) { ++ printk("mmc: error %d in mmc_spi_hardware_init\n", result); ++ return -1; ++ } ++ ++ result = mmc_spi_card_init(); ++ if (result != 0) { ++ // Give it an extra shot ++ result = mmc_spi_card_init(); ++ if (result != 0) { ++ printk("mmc: error %d in mmc_card_init\n", result); ++ return -1; ++ } ++ } ++ ++ memset(hd_sizes, 0, sizeof(hd_sizes)); ++ result = mmc_spi_card_config(); ++ if (result != 0) { ++ printk("mmc: error %d in mmc_card_config\n", result); ++ return -1; ++ } ++ ++ ++ blk_size[MAJOR_NR] = hd_sizes; ++ ++ memset(hd, 0, sizeof(hd)); ++ hd[0].nr_sects = hd_sizes[0] * 2; ++ ++ blksize_size[MAJOR_NR] = hd_blocksizes; ++ hardsect_size[MAJOR_NR] = hd_hardsectsizes; ++ max_sectors[MAJOR_NR] = hd_maxsect; ++ ++ hd_gendisk.nr_real = 1; ++ ++ register_disk(&hd_gendisk, MKDEV(MAJOR_NR, 0), 1 << 6, ++ &mmc_bdops, hd_sizes[0] * 2); ++ ++ return 0; ++} ++ ++static void mmc_exit(void) ++{ ++ blk_size[MAJOR_NR] = NULL; ++ blksize_size[MAJOR_NR] = NULL; ++ hardsect_size[MAJOR_NR] = NULL; ++ max_sectors[MAJOR_NR] = NULL; ++ hd[0].nr_sects = 0; ++} ++ ++static void mmc_check_media(void) ++{ ++ int old_state, new_state; ++ int result; ++ ++ old_state = mmc_media_detect; ++ new_state = mmc_spi_media_detect(); ++ ++ if (old_state != new_state) { ++ mmc_media_changed = 1; ++ if (new_state == PRESENT) { ++ result = mmc_init(); ++ if (result != 0) ++ printk("mmc: error %d in mmc_init\n", result); ++ } else { ++ mmc_exit(); ++ } ++ } ++ ++ /* del_timer(&mmc_timer); ++ mmc_timer.expires = jiffies + 10*HZ; ++ add_timer(&mmc_timer); */ ++} ++ ++static int __init mmc_driver_init(void) ++{ ++ int result; ++ ++ result = devfs_register_blkdev(MAJOR_NR, DEVICE_NAME, &mmc_bdops); ++ if (result < 0) { ++ printk(KERN_WARNING "mmc: can't get major %d\n", MAJOR_NR); ++ return result; ++ } ++ ++ blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), mmc_request); ++ ++ mmc_check_media(); ++ ++ /*init_timer(&mmc_timer); ++ mmc_timer.expires = jiffies + HZ; ++ mmc_timer.function = (void *)mmc_check_media; ++ add_timer(&mmc_timer); */ ++ ++ ++ read_ahead[MAJOR_NR] = 8; ++ add_gendisk(&hd_gendisk); ++ ++ ++ return 0; ++} ++ ++static void __exit mmc_driver_exit(void) ++{ ++ int i; ++ del_timer(&mmc_timer); ++ ++ for (i = 0; i < (1 << 6); i++) ++ fsync_dev(MKDEV(MAJOR_NR, i)); ++ ++ blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); ++ del_gendisk(&hd_gendisk); ++ devfs_unregister_blkdev(MAJOR_NR, DEVICE_NAME); ++ mmc_exit(); ++} ++ ++module_init(mmc_driver_init); ++module_exit(mmc_driver_exit); +--- linux-2.4.27/drivers/block/Config.in~mmc-spi ++++ linux-2.4.27/drivers/block/Config.in +@@ -4,6 +4,7 @@ + mainmenu_option next_comment + comment 'Block devices' + ++tristate 'MMC SPI driver' CONFIG_BLK_DEV_MMC + tristate 'Normal floppy disk support' CONFIG_BLK_DEV_FD + if [ "$CONFIG_AMIGA" = "y" ]; then + tristate 'Amiga floppy support' CONFIG_AMIGA_FLOPPY +--- linux-2.4.27/drivers/block/Makefile~mmc-spi ++++ linux-2.4.27/drivers/block/Makefile +@@ -15,6 +15,7 @@ + obj-y := ll_rw_blk.o blkpg.o genhd.o elevator.o + + obj-$(CONFIG_MAC_FLOPPY) += swim3.o ++obj-$(CONFIG_BLK_DEV_MMC) += mmc.o + obj-$(CONFIG_BLK_DEV_FD) += floppy.o + obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o + obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o diff --git a/recipes/linux/opensimpad/mppe-20040216.patch b/recipes/linux/opensimpad/mppe-20040216.patch new file mode 100644 index 0000000000..c4195c1420 --- /dev/null +++ b/recipes/linux/opensimpad/mppe-20040216.patch @@ -0,0 +1,1225 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/drivers/net/Config.in~mppe-20040216 ++++ linux-2.4.27/drivers/net/Config.in +@@ -332,6 +332,7 @@ + dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP + dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP + dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP $CONFIG_PPP ++ dep_tristate ' PPP MPPE compression (encryption)' CONFIG_PPP_MPPE $CONFIG_PPP + if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then + dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP + fi +--- /dev/null ++++ linux-2.4.27/drivers/net/arcfour.c +@@ -0,0 +1,75 @@ ++/* ++ * arcfour.c ++ * by Frank Cusack <frank@google.com> ++ * 100% public domain ++ * ++ * Implemented from the description in _Applied Cryptography_, 2nd ed. ++ * ++ * ** Distribution ** of this software is unlimited and unrestricted. ++ * ++ * ** Use ** of this software is almost certainly legal; however, refer ++ * to <http://theory.lcs.mit.edu/~rivest/faq.html>. ++ */ ++ ++#include "arcfour.h" ++#if defined(__linux__) ++#include <linux/string.h> ++#endif ++ ++#define swap(a, b) \ ++{ \ ++ unsigned char t = b; \ ++ b = a; \ ++ a = t; \ ++} ++ ++/* ++ * Initialize arcfour from a key. ++ */ ++void ++arcfour_setkey(arcfour_context *context, const unsigned char *key, ++ unsigned keylen) ++{ ++ unsigned i, j; ++ unsigned char K[256]; ++ ++ context->i = context->j = 0; ++ ++ for (i = 0; i < 256; i++) { ++ context->S[i] = i; ++ K[i] = key[i % keylen]; ++ } ++ ++ j = 0; ++ for (i = 0; i < 256; i++) { ++ j = (j + context->S[i] + K[i]) % 256; ++ swap(context->S[i], context->S[j]); ++ } ++ ++ memset(K, 0, sizeof(K)); ++} ++ ++/* ++ * plaintext -> ciphertext (or vice versa) ++ */ ++void ++arcfour_encrypt(arcfour_context *context, const unsigned char *in, unsigned len, ++ unsigned char *out) ++{ ++ unsigned i = context->i; ++ unsigned j = context->j; ++ unsigned char *S = context->S; ++ unsigned char K; ++ ++ while (len--) { ++ i = (i + 1) % 256; ++ j = (j + S[i]) % 256; ++ swap(S[i], S[j]); ++ K = S[(S[i] + S[j]) % 256]; ++ *out++ = *in++ ^ K; ++ } ++ ++ context->i = i; ++ context->j = j; ++} ++ +--- /dev/null ++++ linux-2.4.27/drivers/net/arcfour.h +@@ -0,0 +1,17 @@ ++/* arcfour.h */ ++ ++#ifndef _ARCFOUR_H ++#define _ARCFOUR_H ++ ++typedef struct { ++ unsigned i; ++ unsigned j; ++ unsigned char S[256]; ++} arcfour_context; ++ ++extern void arcfour_setkey(arcfour_context *, const unsigned char *, unsigned); ++extern void arcfour_encrypt(arcfour_context *, const unsigned char *, unsigned, ++ unsigned char *); ++#define arcfour_decrypt arcfour_encrypt ++ ++#endif /* _ARCFOUR_H */ +--- linux-2.4.27/drivers/net/ppp_generic.c~mppe-20040216 ++++ linux-2.4.27/drivers/net/ppp_generic.c +@@ -102,6 +102,7 @@ + spinlock_t rlock; /* lock for receive side 58 */ + spinlock_t wlock; /* lock for transmit side 5c */ + int mru; /* max receive unit 60 */ ++ int mru_alloc; /* MAX(1500,MRU) for dev_alloc_skb() */ + unsigned int flags; /* control bits 64 */ + unsigned int xstate; /* transmit state bits 68 */ + unsigned int rstate; /* receive state bits 6c */ +@@ -129,6 +130,7 @@ + struct sock_fprog pass_filter; /* filter for packets to pass */ + struct sock_fprog active_filter;/* filter for pkts to reset idle */ + #endif /* CONFIG_PPP_FILTER */ ++ int xpad; /* ECP or CCP (MPPE) transmit padding */ + }; + + /* +@@ -552,7 +554,9 @@ + case PPPIOCSMRU: + if (get_user(val, (int *) arg)) + break; +- ppp->mru = val; ++ ppp->mru_alloc = ppp->mru = val; ++ if (ppp->mru_alloc < PPP_MRU) ++ ppp->mru_alloc = PPP_MRU; /* increase for broken peers */ + err = 0; + break; + +@@ -1031,8 +1035,8 @@ + /* try to do packet compression */ + if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0 + && proto != PPP_LCP && proto != PPP_CCP) { +- new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len, +- GFP_ATOMIC); ++ new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len ++ + ppp->xpad, GFP_ATOMIC); + if (new_skb == 0) { + printk(KERN_ERR "PPP: no memory (comp pkt)\n"); + goto drop; +@@ -1044,15 +1048,28 @@ + /* compressor still expects A/C bytes in hdr */ + len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2, + new_skb->data, skb->len + 2, +- ppp->dev->mtu + PPP_HDRLEN); ++ ppp->dev->mtu + ppp->xpad ++ + PPP_HDRLEN); + if (len > 0 && (ppp->flags & SC_CCP_UP)) { + kfree_skb(skb); + skb = new_skb; + skb_put(skb, len); + skb_pull(skb, 2); /* pull off A/C bytes */ +- } else { ++ } else if (len == 0) { + /* didn't compress, or CCP not up yet */ + kfree_skb(new_skb); ++ } else { ++ /* ++ * (len < 0) ++ * MPPE requires that we do not send unencrypted ++ * frames. The compressor will return -1 if we ++ * should drop the frame. We cannot simply test ++ * the compress_proto because MPPE and MPPC share ++ * the same number. ++ */ ++ printk(KERN_ERR "ppp: compressor dropped pkt\n"); ++ kfree_skb(new_skb); ++ goto drop; + } + } + +@@ -1540,14 +1557,15 @@ + int len; + + if (proto == PPP_COMP) { +- ns = dev_alloc_skb(ppp->mru + PPP_HDRLEN); ++ ns = dev_alloc_skb(ppp->mru_alloc + PPP_HDRLEN); + if (ns == 0) { + printk(KERN_ERR "ppp_decompress_frame: no memory\n"); + goto err; + } + /* the decompressor still expects the A/C bytes in the hdr */ + len = ppp->rcomp->decompress(ppp->rc_state, skb->data - 2, +- skb->len + 2, ns->data, ppp->mru + PPP_HDRLEN); ++ skb->len + 2, ns->data, ++ ppp->mru_alloc + PPP_HDRLEN); + if (len < 0) { + /* Pass the compressed frame to pppd as an + error indication. */ +@@ -1982,6 +2000,20 @@ + ocomp->comp_free(ostate); + err = 0; + } ++ if (ccp_option[0] == CI_MPPE) ++ /* ++ * pppd (userland) has reduced the MTU by MPPE_PAD, ++ * to accomodate "compressor" growth. We must ++ * increase the space allocated for compressor ++ * output in ppp_send_frame() accordingly. Note ++ * that from a purist's view, it may be more correct ++ * to require multilink and fragment large packets, ++ * but that seems inefficient compared to this ++ * little trick. ++ */ ++ ppp->xpad = MPPE_PAD; ++ else ++ ppp->xpad = 0; + + } else { + state = cp->decomp_alloc(ccp_option, data.length); +@@ -2253,6 +2285,7 @@ + /* Initialize the new ppp unit */ + ppp->file.index = unit; + ppp->mru = PPP_MRU; ++ ppp->mru_alloc = PPP_MRU; + init_ppp_file(&ppp->file, INTERFACE); + ppp->file.hdrlen = PPP_HDRLEN - 2; /* don't count proto bytes */ + for (i = 0; i < NUM_NP; ++i) +--- /dev/null ++++ linux-2.4.27/drivers/net/ppp_mppe_compress.c +@@ -0,0 +1,643 @@ ++/* ++ * ==FILEVERSION 20020521== ++ * ++ * ppp_mppe_compress.c - interface MPPE to the PPP code. ++ * This version is for use with Linux kernel 2.2.19+ and 2.4.x. ++ * ++ * By Frank Cusack <frank@google.com>. ++ * Copyright (c) 2002 Google, Inc. ++ * All rights reserved. ++ * ++ * Permission to use, copy, modify, and distribute this software and its ++ * documentation is hereby granted, provided that the above copyright ++ * notice appears in all copies. This software is provided without any ++ * warranty, express or implied. ++ * ++ * Changelog: ++ * 2/15/04 - TS: added #include <version.h> and testing for Kernel ++ * version before using ++ * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are ++ * depreciated in 2.6 ++ */ ++ ++#include <linux/module.h> ++#include <linux/kernel.h> ++#include <linux/version.h> ++#include <linux/init.h> ++#include <linux/types.h> ++#include <linux/slab.h> ++#include <linux/string.h> ++ ++#include <linux/ppp_defs.h> ++#include <linux/ppp-comp.h> ++ ++#include "arcfour.h" ++#include "sha1.h" ++ ++/* ++ * State for an MPPE (de)compressor. ++ */ ++typedef struct ppp_mppe_state { ++ unsigned char master_key[MPPE_MAX_KEY_LEN]; ++ unsigned char session_key[MPPE_MAX_KEY_LEN]; ++ arcfour_context arcfour_context; /* encryption state */ ++ unsigned keylen; /* key length in bytes */ ++ /* NB: 128-bit == 16, 40-bit == 8! */ ++ /* If we want to support 56-bit, */ ++ /* the unit has to change to bits */ ++ unsigned char bits; /* MPPE control bits */ ++ unsigned ccount; /* 12-bit coherency count (seqno) */ ++ unsigned stateful; /* stateful mode flag */ ++ int discard; /* stateful mode packet loss flag */ ++ int sanity_errors; /* take down LCP if too many */ ++ int unit; ++ int debug; ++ struct compstat stats; ++} ppp_mppe_state; ++ ++/* ppp_mppe_state.bits definitions */ ++#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ ++#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ ++#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ ++#define MPPE_BIT_D 0x10 /* This is an encrypted frame */ ++ ++#define MPPE_BIT_FLUSHED MPPE_BIT_A ++#define MPPE_BIT_ENCRYPTED MPPE_BIT_D ++ ++#define MPPE_BITS(p) ((p)[4] & 0xf0) ++#define MPPE_CCOUNT(p) ((((p)[4] & 0x0f) << 8) + (p)[5]) ++#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ ++ ++#define MPPE_OVHD 2 /* MPPE overhead/packet */ ++#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ ++ ++static void GetNewKeyFromSHA __P((unsigned char *StartKey, ++ unsigned char *SessionKey, ++ unsigned SessionKeyLength, ++ unsigned char *InterimKey)); ++static void mppe_rekey __P((ppp_mppe_state *state, int)); ++static void *mppe_alloc __P((unsigned char *options, int optlen)); ++static void mppe_free __P((void *state)); ++static int mppe_init __P((void *state, unsigned char *options, ++ int optlen, int unit, int debug, const char *)); ++static int mppe_comp_init __P((void *state, unsigned char *options, ++ int optlen, ++ int unit, int hdrlen, int debug)); ++static int mppe_decomp_init __P((void *state, unsigned char *options, ++ int optlen, int unit, ++ int hdrlen, int mru, int debug)); ++static int mppe_compress __P((void *state, unsigned char *ibuf, ++ unsigned char *obuf, ++ int isize, int osize)); ++static void mppe_incomp __P((void *state, unsigned char *ibuf, int icnt)); ++static int mppe_decompress __P((void *state, unsigned char *ibuf, ++ int isize, unsigned char *obuf,int osize)); ++static void mppe_comp_reset __P((void *state)); ++static void mppe_decomp_reset __P((void *state)); ++static void mppe_comp_stats __P((void *state, struct compstat *stats)); ++ ++ ++/* ++ * Key Derivation, from RFC 3078, RFC 3079. ++ * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. ++ */ ++static void ++GetNewKeyFromSHA(unsigned char *MasterKey, unsigned char *SessionKey, ++ unsigned SessionKeyLength, unsigned char *InterimKey) ++{ ++ SHA1_CTX Context; ++ unsigned char Digest[SHA1_SIGNATURE_SIZE]; ++ ++ unsigned char SHApad1[40] = ++ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; ++ unsigned char SHApad2[40] = ++ { 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, ++ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, ++ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, ++ 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2 }; ++ ++ /* assert(SessionKeyLength <= SHA1_SIGNATURE_SIZE); */ ++ ++ SHA1_Init(&Context); ++ SHA1_Update(&Context, MasterKey, SessionKeyLength); ++ SHA1_Update(&Context, SHApad1, sizeof(SHApad1)); ++ SHA1_Update(&Context, SessionKey, SessionKeyLength); ++ SHA1_Update(&Context, SHApad2, sizeof(SHApad2)); ++ SHA1_Final(Digest, &Context); ++ ++ memcpy(InterimKey, Digest, SessionKeyLength); ++} ++ ++/* ++ * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. ++ * Well, not what's written there, but rather what they meant. ++ */ ++static void ++mppe_rekey(ppp_mppe_state *state, int initial_key) ++{ ++ unsigned char InterimKey[MPPE_MAX_KEY_LEN]; ++ ++ GetNewKeyFromSHA(state->master_key, state->session_key, ++ state->keylen, InterimKey); ++ if (!initial_key) { ++ arcfour_setkey(&state->arcfour_context, InterimKey, state->keylen); ++ arcfour_encrypt(&state->arcfour_context, InterimKey, state->keylen, ++ state->session_key); ++ } else { ++ memcpy(state->session_key, InterimKey, state->keylen); ++ } ++ if (state->keylen == 8) { ++ /* See RFC 3078 */ ++ state->session_key[0] = 0xd1; ++ state->session_key[1] = 0x26; ++ state->session_key[2] = 0x9e; ++ } ++ arcfour_setkey(&state->arcfour_context, state->session_key, state->keylen); ++} ++ ++ ++/* ++ * Allocate space for a (de)compressor. ++ */ ++static void * ++mppe_alloc(unsigned char *options, int optlen) ++{ ++ ppp_mppe_state *state; ++ ++ if (optlen != CILEN_MPPE + sizeof(state->master_key) ++ || options[0] != CI_MPPE ++ || options[1] != CILEN_MPPE) ++ return NULL; ++ ++ state = (ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL); ++ if (state == NULL) ++ return NULL; ++ ++/* ++ Added to avoid module warnings about MOD_INC ++ being depreciated in 2.6.x ++*/ ++#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) ++ try_module_get(THIS_MODULE); ++#else ++ MOD_INC_USE_COUNT; ++#endif ++ memset(state, 0, sizeof(*state)); ++ ++ /* Save keys. */ ++ memcpy(state->master_key, &options[CILEN_MPPE], sizeof(state->master_key)); ++ memcpy(state->session_key, state->master_key, sizeof(state->master_key)); ++ /* ++ * We defer initial key generation until mppe_init(), as mppe_alloc() ++ * is called frequently during negotiation. ++ */ ++ ++ return (void *) state; ++} ++ ++/* ++ * Deallocate space for a (de)compressor. ++ */ ++static void ++mppe_free(void *arg) ++{ ++ ppp_mppe_state *state = (ppp_mppe_state *) arg; ++ ++ if (state) { ++ kfree(state); ++/* ++ Added to avoid module warnings about MOD_DEC_USE_COUNT ++ being depreciated in 2.6.x ++*/ ++#if ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) ++ module_put(THIS_MODULE); ++#else ++ MOD_DEC_USE_COUNT; ++#endif ++ } ++} ++ ++ ++/* ++ * Initialize (de)compressor state. ++ */ ++static int ++mppe_init(void *arg, unsigned char *options, int optlen, int unit, int debug, ++ const char *debugstr) ++{ ++ ppp_mppe_state *state = (ppp_mppe_state *) arg; ++ unsigned char mppe_opts; ++ ++ if (optlen != CILEN_MPPE ++ || options[0] != CI_MPPE ++ || options[1] != CILEN_MPPE) ++ return 0; ++ ++ MPPE_CI_TO_OPTS(&options[2], mppe_opts); ++ if (mppe_opts & MPPE_OPT_128) ++ state->keylen = 16; ++ else if (mppe_opts & MPPE_OPT_40) ++ state->keylen = 8; ++ else { ++ printk(KERN_WARNING "%s[%d]: unknown key length\n", debugstr, unit); ++ return 0; ++ } ++ if (mppe_opts & MPPE_OPT_STATEFUL) ++ state->stateful = 1; ++ ++ /* Generate the initial session key. */ ++ mppe_rekey(state, 1); ++ ++ if (debug) { ++ int i; ++ char mkey[sizeof(state->master_key) * 2 + 1]; ++ char skey[sizeof(state->session_key) * 2 + 1]; ++ ++ printk(KERN_DEBUG "%s[%d]: initialized with %d-bit %s mode\n", debugstr, ++ unit, (state->keylen == 16)? 128: 40, ++ (state->stateful)? "stateful": "stateless"); ++ ++ for (i = 0; i < sizeof(state->master_key); i++) ++ sprintf(mkey + i * 2, "%.2x", state->master_key[i]); ++ for (i = 0; i < sizeof(state->session_key); i++) ++ sprintf(skey + i * 2, "%.2x", state->session_key[i]); ++ printk(KERN_DEBUG "%s[%d]: keys: master: %s initial session: %s\n", ++ debugstr, unit, mkey, skey); ++ } ++ ++ /* ++ * Initialize the coherency count. The initial value is not specified ++ * in RFC 3078, but we can make a reasonable assumption that it will ++ * start at 0. Setting it to the max here makes the comp/decomp code ++ * do the right thing (determined through experiment). ++ */ ++ state->ccount = MPPE_CCOUNT_SPACE - 1; ++ ++ /* ++ * Note that even though we have initialized the key table, we don't ++ * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. ++ */ ++ state->bits = MPPE_BIT_ENCRYPTED; ++ ++ state->unit = unit; ++ state->debug = debug; ++ ++ return 1; ++} ++ ++ ++ ++static int ++mppe_comp_init(void *arg, unsigned char *options, int optlen, int unit, ++ int hdrlen, int debug) ++{ ++ /* ARGSUSED */ ++ return mppe_init(arg, options, optlen, unit, debug, "mppe_comp_init"); ++} ++ ++/* ++ * We received a CCP Reset-Request (actually, we are sending a Reset-Ack), ++ * tell the compressor to rekey. Note that we MUST NOT rekey for ++ * every CCP Reset-Request; we only rekey on the next xmit packet. ++ * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. ++ * So, rekeying for every CCP Reset-Request is broken as the peer will not ++ * know how many times we've rekeyed. (If we rekey and THEN get another ++ * CCP Reset-Request, we must rekey again.) ++ */ ++static void ++mppe_comp_reset(void *arg) ++{ ++ ppp_mppe_state *state = (ppp_mppe_state *) arg; ++ ++ state->bits |= MPPE_BIT_FLUSHED; ++} ++ ++/* ++ * Compress (encrypt) a packet. ++ * It's strange to call this a compressor, since the output is always ++ * MPPE_OVHD + 2 bytes larger than the input. ++ */ ++int ++mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, ++ int isize, int osize) ++{ ++ ppp_mppe_state *state = (ppp_mppe_state *) arg; ++ int proto; ++ ++ /* ++ * Check that the protocol is in the range we handle. ++ */ ++ proto = PPP_PROTOCOL(ibuf); ++ if (proto < 0x0021 || proto > 0x00fa) ++ return 0; ++ ++ /* Make sure we have enough room to generate an encrypted packet. */ ++ if (osize < isize + MPPE_OVHD + 2) { ++ /* Drop the packet if we should encrypt it, but can't. */ ++ printk(KERN_DEBUG "mppe_compress[%d]: osize too small! " ++ "(have: %d need: %d)\n", state->unit, ++ osize, osize + MPPE_OVHD + 2); ++ return -1; ++ } ++ ++ osize = isize + MPPE_OVHD + 2; ++ ++ /* ++ * Copy over the PPP header and set control bits. ++ */ ++ obuf[0] = PPP_ADDRESS(ibuf); ++ obuf[1] = PPP_CONTROL(ibuf); ++ obuf[2] = PPP_COMP >> 8; /* isize + MPPE_OVHD + 1 */ ++ obuf[3] = PPP_COMP; /* isize + MPPE_OVHD + 2 */ ++ obuf += PPP_HDRLEN; ++ ++ state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; ++ if (state->debug >= 7) ++ printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit, ++ state->ccount); ++ obuf[0] = state->ccount >> 8; ++ obuf[1] = state->ccount & 0xff; ++ ++ if (!state->stateful || /* stateless mode */ ++ ((state->ccount & 0xff) == 0xff) || /* "flag" packet */ ++ (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ ++ /* We must rekey */ ++ if (state->debug && state->stateful) ++ printk(KERN_DEBUG "mppe_compress[%d]: rekeying\n", state->unit); ++ mppe_rekey(state, 0); ++ state->bits |= MPPE_BIT_FLUSHED; ++ } ++ obuf[0] |= state->bits; ++ state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ ++ ++ obuf += MPPE_OVHD; ++ ibuf += 2; /* skip to proto field */ ++ isize -= 2; ++ ++ /* Encrypt packet */ ++ arcfour_encrypt(&state->arcfour_context, ibuf, isize, obuf); ++ ++ state->stats.unc_bytes += isize; ++ state->stats.unc_packets++; ++ state->stats.comp_bytes += osize; ++ state->stats.comp_packets++; ++ ++ return osize; ++} ++ ++/* ++ * Since every frame grows by MPPE_OVHD + 2 bytes, this is always going ++ * to look bad ... and the longer the link is up the worse it will get. ++ */ ++static void ++mppe_comp_stats(void *arg, struct compstat *stats) ++{ ++ ppp_mppe_state *state = (ppp_mppe_state *) arg; ++ ++ *stats = state->stats; ++} ++ ++ ++static int ++mppe_decomp_init(void *arg, unsigned char *options, int optlen, int unit, ++ int hdrlen, int mru, int debug) ++{ ++ /* ARGSUSED */ ++ return mppe_init(arg, options, optlen, unit, debug, "mppe_decomp_init"); ++} ++ ++/* ++ * We received a CCP Reset-Ack. Just ignore it. ++ */ ++static void ++mppe_decomp_reset(void *arg) ++{ ++ /* ARGSUSED */ ++ return; ++} ++ ++/* ++ * Decompress (decrypt) an MPPE packet. ++ */ ++int ++mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, ++ int osize) ++{ ++ ppp_mppe_state *state = (ppp_mppe_state *) arg; ++ unsigned ccount; ++ int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED; ++ int sanity = 0; ++ ++ if (isize <= PPP_HDRLEN + MPPE_OVHD) { ++ if (state->debug) ++ printk(KERN_DEBUG "mppe_decompress[%d]: short pkt (%d)\n", ++ state->unit, isize); ++ return DECOMP_ERROR; ++ } ++ ++ /* Make sure we have enough room to decrypt the packet. */ ++ if (osize < isize - MPPE_OVHD - 2) { ++ printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! " ++ "(have: %d need: %d)\n", state->unit, ++ osize, isize - MPPE_OVHD - 2); ++ return DECOMP_ERROR; ++ } ++ osize = isize - MPPE_OVHD - 2; ++ ++ ccount = MPPE_CCOUNT(ibuf); ++ if (state->debug >= 7) ++ printk(KERN_DEBUG "mppe_decompress[%d]: ccount %d\n", state->unit, ++ ccount); ++ ++ /* sanity checks -- terminate with extreme prejudice */ ++ if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) { ++ printk(KERN_DEBUG "mppe_decompress[%d]: ENCRYPTED bit not set!\n", ++ state->unit); ++ state->sanity_errors += 100; ++ sanity = 1; ++ } ++ if (!state->stateful && !flushed) { ++ printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in " ++ "stateless mode!\n", state->unit); ++ state->sanity_errors += 100; ++ sanity = 1; ++ } ++ if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { ++ printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on " ++ "flag packet!\n", state->unit); ++ state->sanity_errors += 100; ++ sanity = 1; ++ } ++ ++ if (sanity) { ++ if (state->sanity_errors < SANITY_MAX) ++ return DECOMP_ERROR; ++ else ++ /* ++ * Take LCP down if the peer is sending too many bogons. ++ * We don't want to do this for a single or just a few ++ * instances since it could just be due to packet corruption. ++ */ ++ return DECOMP_FATALERROR; ++ } ++ ++ /* ++ * Check the coherency count. ++ */ ++ ++ if (!state->stateful) { ++ /* RFC 3078, sec 8.1. Rekey for every packet. */ ++ while (state->ccount != ccount) { ++ mppe_rekey(state, 0); ++ state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; ++ } ++ } else { ++ /* RFC 3078, sec 8.2. */ ++ if (!state->discard) { ++ /* normal state */ ++ state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; ++ if (ccount != state->ccount) { ++ /* ++ * (ccount > state->ccount) ++ * Packet loss detected, enter the discard state. ++ * Signal the peer to rekey (by sending a CCP Reset-Request). ++ */ ++ state->discard = 1; ++ return DECOMP_ERROR; ++ } ++ } else { ++ /* discard state */ ++ if (!flushed) { ++ /* ccp.c will be silent (no additional CCP Reset-Requests). */ ++ return DECOMP_ERROR; ++ } else { ++ /* Rekey for every missed "flag" packet. */ ++ while ((ccount & ~0xff) != (state->ccount & ~0xff)) { ++ mppe_rekey(state, 0); ++ state->ccount = (state->ccount + 256) % MPPE_CCOUNT_SPACE; ++ } ++ ++ /* reset */ ++ state->discard = 0; ++ state->ccount = ccount; ++ /* ++ * Another problem with RFC 3078 here. It implies that the ++ * peer need not send a Reset-Ack packet. But RFC 1962 ++ * requires it. Hopefully, M$ does send a Reset-Ack; even ++ * though it isn't required for MPPE synchronization, it is ++ * required to reset CCP state. ++ */ ++ } ++ } ++ if (flushed) ++ mppe_rekey(state, 0); ++ } ++ ++ /* ++ * Fill in the first part of the PPP header. The protocol field ++ * comes from the decrypted data. ++ */ ++ obuf[0] = PPP_ADDRESS(ibuf); /* +1 */ ++ obuf[1] = PPP_CONTROL(ibuf); /* +1 */ ++ obuf += 2; ++ ibuf += PPP_HDRLEN + MPPE_OVHD; ++ isize -= PPP_HDRLEN + MPPE_OVHD; /* -6 */ ++ /* net osize: isize-4 */ ++ ++ /* And finally, decrypt the packet. */ ++ arcfour_decrypt(&state->arcfour_context, ibuf, isize, obuf); ++ ++ state->stats.unc_bytes += osize; ++ state->stats.unc_packets++; ++ state->stats.comp_bytes += isize; ++ state->stats.comp_packets++; ++ ++ /* good packet credit */ ++ state->sanity_errors >>= 1; ++ ++ return osize; ++} ++ ++/* ++ * Incompressible data has arrived (this should never happen!). ++ * We should probably drop the link if the protocol is in the range ++ * of what should be encrypted. At the least, we should drop this ++ * packet. (How to do this?) ++ */ ++static void ++mppe_incomp(void *arg, unsigned char *ibuf, int icnt) ++{ ++ ppp_mppe_state *state = (ppp_mppe_state *) arg; ++ ++ if (state->debug && ++ (PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa)) ++ printk(KERN_DEBUG "mppe_incomp[%d]: incompressible (unencrypted) data! " ++ "(proto %04x)\n", state->unit, PPP_PROTOCOL(ibuf)); ++ ++ state->stats.inc_bytes += icnt; ++ state->stats.inc_packets++; ++ state->stats.unc_bytes += icnt; ++ state->stats.unc_packets++; ++} ++ ++/************************************************************* ++ * Module interface table ++ *************************************************************/ ++ ++/* These are in ppp.c (2.2.x) or ppp_generic.c (2.4.x) */ ++extern int ppp_register_compressor (struct compressor *cp); ++extern void ppp_unregister_compressor (struct compressor *cp); ++ ++/* ++ * Procedures exported to if_ppp.c. ++ */ ++struct compressor ppp_mppe = { ++ CI_MPPE, /* compress_proto */ ++ mppe_alloc, /* comp_alloc */ ++ mppe_free, /* comp_free */ ++ mppe_comp_init, /* comp_init */ ++ mppe_comp_reset, /* comp_reset */ ++ mppe_compress, /* compress */ ++ mppe_comp_stats, /* comp_stat */ ++ mppe_alloc, /* decomp_alloc */ ++ mppe_free, /* decomp_free */ ++ mppe_decomp_init, /* decomp_init */ ++ mppe_decomp_reset, /* decomp_reset */ ++ mppe_decompress, /* decompress */ ++ mppe_incomp, /* incomp */ ++ mppe_comp_stats, /* decomp_stat */ ++}; ++ ++/* 2.2 compatibility defines */ ++#ifndef __init ++#define __init ++#endif ++#ifndef __exit ++#define __exit ++#endif ++#ifndef MODULE_LICENSE ++#define MODULE_LICENSE(license) ++#endif ++ ++int __init ++ppp_mppe_init(void) ++{ ++ int answer = ppp_register_compressor(&ppp_mppe); ++ ++ if (answer == 0) ++ printk(KERN_INFO "PPP MPPE Compression module registered\n"); ++ return answer; ++} ++ ++void __exit ++ppp_mppe_cleanup(void) ++{ ++ ppp_unregister_compressor(&ppp_mppe); ++} ++ ++module_init(ppp_mppe_init); ++module_exit(ppp_mppe_cleanup); ++MODULE_LICENSE("BSD without advertisement clause"); +--- /dev/null ++++ linux-2.4.27/drivers/net/sha1.c +@@ -0,0 +1,185 @@ ++/* ++ * ftp://ftp.funet.fi/pub/crypt/hash/sha/sha1.c ++ * ++ * SHA-1 in C ++ * By Steve Reid <steve@edmweb.com> ++ * 100% Public Domain ++ * ++ * Test Vectors (from FIPS PUB 180-1) ++ * "abc" ++ * A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D ++ * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" ++ * 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 ++ * A million repetitions of "a" ++ * 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F ++ */ ++ ++/* #define SHA1HANDSOFF * Copies data before messing with it. */ ++ ++#if defined(__linux__) ++#include <asm/byteorder.h> ++#include <linux/string.h> ++#elif defined(__solaris__) ++#include <sys/isa_defs.h> ++#include <sys/ddi.h> ++#include <sys/sunddi.h> ++#define memcpy(d, s, c) bcopy(s, d, c) ++#define memset(d, b, c) bzero(d, c) ++#endif ++ ++#include "sha1.h" ++ ++static void SHA1_Transform(unsigned long[5], const unsigned char[64]); ++ ++#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) ++ ++/* blk0() and blk() perform the initial expand. */ ++/* I got the idea of expanding during the round function from SSLeay */ ++#if defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN) ++#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ ++ |(rol(block->l[i],8)&0x00FF00FF)) ++#elif defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN) ++#define blk0(i) block->l[i] ++#else ++#error Endianness not defined ++#endif ++#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ ++ ^block->l[(i+2)&15]^block->l[i&15],1)) ++ ++/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ ++#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); ++#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); ++#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); ++#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); ++#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); ++ ++ ++/* Hash a single 512-bit block. This is the core of the algorithm. */ ++ ++static void ++SHA1_Transform(unsigned long state[5], const unsigned char buffer[64]) ++{ ++ unsigned long a, b, c, d, e; ++ typedef union { ++ unsigned char c[64]; ++ unsigned long l[16]; ++ } CHAR64LONG16; ++ CHAR64LONG16 *block; ++ ++#ifdef SHA1HANDSOFF ++ static unsigned char workspace[64]; ++ block = (CHAR64LONG16 *) workspace; ++ memcpy(block, buffer, 64); ++#else ++ block = (CHAR64LONG16 *) buffer; ++#endif ++ /* Copy context->state[] to working vars */ ++ a = state[0]; ++ b = state[1]; ++ c = state[2]; ++ d = state[3]; ++ e = state[4]; ++ /* 4 rounds of 20 operations each. Loop unrolled. */ ++ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); ++ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); ++ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); ++ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); ++ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); ++ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); ++ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); ++ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); ++ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); ++ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); ++ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); ++ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); ++ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); ++ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); ++ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); ++ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); ++ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); ++ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); ++ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); ++ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); ++ /* Add the working vars back into context.state[] */ ++ state[0] += a; ++ state[1] += b; ++ state[2] += c; ++ state[3] += d; ++ state[4] += e; ++ /* Wipe variables */ ++ a = b = c = d = e = 0; ++} ++ ++ ++/* SHA1Init - Initialize new context */ ++ ++void ++SHA1_Init(SHA1_CTX *context) ++{ ++ /* SHA1 initialization constants */ ++ context->state[0] = 0x67452301; ++ context->state[1] = 0xEFCDAB89; ++ context->state[2] = 0x98BADCFE; ++ context->state[3] = 0x10325476; ++ context->state[4] = 0xC3D2E1F0; ++ context->count[0] = context->count[1] = 0; ++} ++ ++ ++/* Run your data through this. */ ++ ++void ++SHA1_Update(SHA1_CTX *context, const unsigned char *data, unsigned int len) ++{ ++ unsigned int i, j; ++ ++ j = (context->count[0] >> 3) & 63; ++ if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; ++ context->count[1] += (len >> 29); ++ if ((j + len) > 63) { ++ memcpy(&context->buffer[j], data, (i = 64-j)); ++ SHA1_Transform(context->state, context->buffer); ++ for ( ; i + 63 < len; i += 64) { ++ SHA1_Transform(context->state, &data[i]); ++ } ++ j = 0; ++ } ++ else ++ i = 0; ++ ++ memcpy(&context->buffer[j], &data[i], len - i); ++} ++ ++ ++/* Add padding and return the message digest. */ ++ ++void ++SHA1_Final(unsigned char digest[20], SHA1_CTX *context) ++{ ++ unsigned long i, j; ++ unsigned char finalcount[8]; ++ ++ for (i = 0; i < 8; i++) { ++ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] ++ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ ++ } ++ SHA1_Update(context, (unsigned char *) "\200", 1); ++ while ((context->count[0] & 504) != 448) { ++ SHA1_Update(context, (unsigned char *) "\0", 1); ++ } ++ SHA1_Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ ++ for (i = 0; i < 20; i++) { ++ digest[i] = (unsigned char) ++ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); ++ } ++ /* Wipe variables */ ++ i = j = 0; ++ memset(context->buffer, 0, 64); ++ memset(context->state, 0, 20); ++ memset(context->count, 0, 8); ++ memset(&finalcount, 0, 8); ++#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ ++ SHA1Transform(context->state, context->buffer); ++#endif ++} ++ +--- /dev/null ++++ linux-2.4.27/drivers/net/sha1.h +@@ -0,0 +1,18 @@ ++/* sha1.h */ ++ ++#ifndef _SHA1_H ++#define _SHA1_H ++ ++typedef struct { ++ unsigned long state[5]; ++ unsigned long count[2]; ++ unsigned char buffer[64]; ++} SHA1_CTX; ++ ++#define SHA1_SIGNATURE_SIZE 20 ++ ++extern void SHA1_Init(SHA1_CTX *); ++extern void SHA1_Update(SHA1_CTX *, const unsigned char *, unsigned int); ++extern void SHA1_Final(unsigned char[SHA1_SIGNATURE_SIZE], SHA1_CTX *); ++ ++#endif /* _SHA1_H */ +--- linux-2.4.27/include/linux/ppp-comp.h~mppe-20040216 ++++ linux-2.4.27/include/linux/ppp-comp.h +@@ -187,6 +187,100 @@ + #define DEFLATE_CHK_SEQUENCE 0 + + /* ++ * Definitions for MPPE. ++ */ ++ ++#define CI_MPPE 18 /* config option for MPPE */ ++#define CILEN_MPPE 6 /* length of config option */ ++ ++#define MPPE_PAD 4 /* MPPE growth per frame */ ++#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ ++ ++/* option bits for ccp_options.mppe */ ++#define MPPE_OPT_40 0x01 /* 40 bit */ ++#define MPPE_OPT_128 0x02 /* 128 bit */ ++#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */ ++/* unsupported opts */ ++#define MPPE_OPT_56 0x08 /* 56 bit */ ++#define MPPE_OPT_MPPC 0x10 /* MPPC compression */ ++#define MPPE_OPT_D 0x20 /* Unknown */ ++#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D) ++#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */ ++ ++/* ++ * This is not nice ... the alternative is a bitfield struct though. ++ * And unfortunately, we cannot share the same bits for the option ++ * names above since C and H are the same bit. We could do a u_int32 ++ * but then we have to do a htonl() all the time and/or we still need ++ * to know which octet is which. ++ */ ++#define MPPE_C_BIT 0x01 /* MPPC */ ++#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */ ++#define MPPE_L_BIT 0x20 /* 40-bit */ ++#define MPPE_S_BIT 0x40 /* 128-bit */ ++#define MPPE_M_BIT 0x80 /* 56-bit, not supported */ ++#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */ ++ ++/* Does not include H bit; used for least significant octet only. */ ++#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT) ++ ++/* Build a CI from mppe opts (see RFC 3078) */ ++#define MPPE_OPTS_TO_CI(opts, ci) \ ++ do { \ ++ u_char *ptr = ci; /* u_char[4] */ \ ++ \ ++ /* H bit */ \ ++ if (opts & MPPE_OPT_STATEFUL) \ ++ *ptr++ = 0x0; \ ++ else \ ++ *ptr++ = MPPE_H_BIT; \ ++ *ptr++ = 0; \ ++ *ptr++ = 0; \ ++ \ ++ /* S,L bits */ \ ++ *ptr = 0; \ ++ if (opts & MPPE_OPT_128) \ ++ *ptr |= MPPE_S_BIT; \ ++ if (opts & MPPE_OPT_40) \ ++ *ptr |= MPPE_L_BIT; \ ++ /* M,D,C bits not supported */ \ ++ } while (/* CONSTCOND */ 0) ++ ++/* The reverse of the above */ ++#define MPPE_CI_TO_OPTS(ci, opts) \ ++ do { \ ++ u_char *ptr = ci; /* u_char[4] */ \ ++ \ ++ opts = 0; \ ++ \ ++ /* H bit */ \ ++ if (!(ptr[0] & MPPE_H_BIT)) \ ++ opts |= MPPE_OPT_STATEFUL; \ ++ \ ++ /* S,L bits */ \ ++ if (ptr[3] & MPPE_S_BIT) \ ++ opts |= MPPE_OPT_128; \ ++ if (ptr[3] & MPPE_L_BIT) \ ++ opts |= MPPE_OPT_40; \ ++ \ ++ /* M,D,C bits */ \ ++ if (ptr[3] & MPPE_M_BIT) \ ++ opts |= MPPE_OPT_56; \ ++ if (ptr[3] & MPPE_D_BIT) \ ++ opts |= MPPE_OPT_D; \ ++ if (ptr[3] & MPPE_C_BIT) \ ++ opts |= MPPE_OPT_MPPC; \ ++ \ ++ /* Other bits */ \ ++ if (ptr[0] & ~MPPE_H_BIT) \ ++ opts |= MPPE_OPT_UNKNOWN; \ ++ if (ptr[1] || ptr[2]) \ ++ opts |= MPPE_OPT_UNKNOWN; \ ++ if (ptr[3] & ~MPPE_ALL_BITS) \ ++ opts |= MPPE_OPT_UNKNOWN; \ ++ } while (/* CONSTCOND */ 0) ++ ++/* + * Definitions for other, as yet unsupported, compression methods. + */ + +--- linux-2.4.27/drivers/net/Makefile~mppe-20040216 ++++ linux-2.4.27/drivers/net/Makefile +@@ -18,8 +18,9 @@ + export-objs := 8390.o arlan.o aironet4500_core.o aironet4500_card.o \ + ppp_async.o ppp_generic.o slhc.o pppox.o auto_irq.o \ + net_init.o mii.o +-list-multi := rcpci.o ++list-multi := rcpci.o ppp_mppe.o + rcpci-objs := rcpci45.o rclanmtl.o ++ppp_mppe-objs := ppp_mppe_compress.o sha1.o arcfour.o + + ifeq ($(CONFIG_TULIP),y) + obj-y += tulip/tulip.o +@@ -164,6 +165,14 @@ + obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o + obj-$(CONFIG_PPPOE) += pppox.o pppoe.o + ++ifeq ($(CONFIG_PPP_MPPE),y) ++ obj-y += $(ppp_mppe-objs) ++else ++ ifeq ($(CONFIG_PPP_MPPE),m) ++ obj-m += ppp_mppe.o ++ endif ++endif ++ + obj-$(CONFIG_SLIP) += slip.o + ifeq ($(CONFIG_SLIP_COMPRESSED),y) + obj-$(CONFIG_SLIP) += slhc.o +@@ -272,3 +281,7 @@ + + rcpci.o: $(rcpci-objs) + $(LD) -r -o $@ $(rcpci-objs) ++ ++ppp_mppe.o: $(ppp_mppe-objs) ++ $(LD) -r -o $@ $(ppp_mppe-objs) ++ diff --git a/recipes/linux/opensimpad/sa1100-usb-tcl1.patch b/recipes/linux/opensimpad/sa1100-usb-tcl1.patch new file mode 100644 index 0000000000..da7f50d120 --- /dev/null +++ b/recipes/linux/opensimpad/sa1100-usb-tcl1.patch @@ -0,0 +1,216 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/arch/arm/mach-sa1100/sa1100_usb.h~sa1100-usb ++++ linux-2.4.27/arch/arm/mach-sa1100/sa1100_usb.h +@@ -10,6 +10,11 @@ + #define _SA1100_USB_H + #include <asm/byteorder.h> + ++#define SA1100_USB_DEBUG ++#ifdef SA1100_USB_DEBUG ++extern int sa1100_usb_debug; ++#endif ++ + typedef void (*usb_callback_t)(int flag, int size); + + /* in usb_ctl.c (see also descriptor methods at bottom of file) */ +--- linux-2.4.27/arch/arm/mach-sa1100/usb_ctl.c~sa1100-usb ++++ linux-2.4.27/arch/arm/mach-sa1100/usb_ctl.c +@@ -28,6 +28,12 @@ + #include "sa1100_usb.h" + #include "usb_ctl.h" + ++// Toby Churchill Ltd modification to re assert Ser0UDCOMP when it gets corrupted (why?) ++// Identified by Chris Jones for TCL. ++// Added 25/3/2004 N C Bane for balloon board. ++#define TCL_FIX ++ ++ + ////////////////////////////////////////////////////////////////////////////// + // Prototypes + ////////////////////////////////////////////////////////////////////////////// +@@ -109,6 +115,45 @@ + ////////////////////////////////////////////////////////////////////////////// + // Async + ////////////////////////////////////////////////////////////////////////////// ++ ++#ifdef CONFIG_SA1100_USB_HOTPLUG ++// user space notification support for sa1100 usb state change ++// Copyright (c) 2003 N C Bane ++#include <linux/kmod.h> ++#include <linux/interrupt.h> ++//static int usb_hotplug_state=USB_STATE_DEFAULT; ++ ++static void do_usb_helper (void *status) ++{ ++ char *argv [3], *envp [3]; ++ int v; ++ ++ argv [0] = "/sbin/sausb-hotplug"; ++ ++ argv [1] = device_state_names[(int)status]; ++ argv [2] = NULL; ++ ++ envp [0] = "HOME=/"; ++ envp [1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; ++ envp [2] = NULL; ++ ++ v = call_usermodehelper (argv [0], argv, envp); ++ ++ if (v != 0) ++ printk ("sausb hotplug returned 0x%x", v); ++} ++ ++static struct tq_struct usb_task; ++ ++static void usb_helper (int status) { ++// usb_hotplug_state = status; ++ usb_task.routine=do_usb_helper; ++ usb_task.data=(void *)status; ++ schedule_task(&usb_task); ++} ++ ++#endif ++ + static void core_kicker(void); + + static inline void enable_resume_mask_suspend( void ); +@@ -119,6 +164,7 @@ + { + __u32 status = Ser0UDCSR; + ++//static int reset; + /* ReSeT Interrupt Request - UDC has been reset */ + if ( status & UDCSR_RSTIR ) + { +@@ -133,6 +179,7 @@ + // mask reset ints, they flood during sequence, enable + // suspend and resume + Ser0UDCCR |= UDCCR_REM; // mask reset ++//reset=true; + Ser0UDCCR &= ~(UDCCR_SUSIM | UDCCR_RESIM); // enable suspend and resume + UDC_flip( Ser0UDCSR, status ); // clear all pending sources + return; // <-- no reason to continue if resetting +@@ -160,6 +207,13 @@ + if (status & UDCSR_EIR) + ep0_int_hndlr(); + ++#ifdef TCL_FIX ++ if (Ser0UDCOMP!=63) { ++ printk("%s: Ser0UDCOMP = %d. Reset to 63\n",__FUNCTION__,Ser0UDCOMP); ++ Ser0UDCOMP=63; ++ } ++#endif ++ + if (status & UDCSR_RIR) + ep1_int_hndlr(status); + +@@ -443,6 +497,12 @@ + ) { + configured_callback(); + } ++#ifdef CONFIG_SA1100_USB_HOTPLUG ++ if (next_device_state == USB_STATE_CONFIGURED) ++ usb_helper(next_device_state); ++ if ((next_device_state == USB_STATE_SUSPENDED) && (usbd_info.state == USB_STATE_CONFIGURED)) ++ usb_helper(next_device_state); ++#endif + usbd_info.state = next_device_state; + ep1_state_change_notify( next_device_state ); + ep2_state_change_notify( next_device_state ); +@@ -683,6 +743,43 @@ + return len; + } + ++#ifdef SA1100_USB_DEBUG ++#include <asm/uaccess.h> /* to copy to/from userspace */ ++struct proc_dir_entry *debug_entry; ++ ++static int proc_debug_read (struct file * file, char * buf, ++ size_t nbytes, loff_t *ppos) ++{ ++ char outputbuf[8]; ++ int count; ++ // read completed? ++ if (*ppos) ++ return 0; ++ count=sprintf(outputbuf, "%d\n",sa1100_usb_debug); ++ if (copy_to_user(buf, outputbuf, count)) ++ return -EFAULT; ++ return count; ++} ++ ++static ssize_t proc_debug_write(struct file * file, const char * buffer, ++ size_t count, loff_t *ppos) ++{ ++ char *endp; ++ if (*ppos) ++ return -EINVAL; ++ sa1100_usb_debug = simple_strtoul(buffer,&endp,0); ++ // we claim all is read ++ return count; ++} ++ ++ ++ ++static struct file_operations proc_debug_operations = { ++ read: proc_debug_read, ++ write: proc_debug_write ++}; ++ ++#endif + #endif /* CONFIG_PROC_FS */ + + ////////////////////////////////////////////////////////////////////////////// +@@ -703,6 +800,15 @@ + + #if CONFIG_PROC_FS + create_proc_read_entry ( PROC_NODE_NAME, 0, NULL, usbctl_read_proc, NULL); ++#ifdef SA1100_USB_DEBUG ++ { ++ debug_entry = create_proc_entry("sa1100_usb_debug", ++ S_IWUSR |S_IRUSR | S_IRGRP | S_IROTH, ++ &proc_root); ++ if (debug_entry) ++ debug_entry->proc_fops = &proc_debug_operations; ++ } ++#endif + #endif + + /* setup rx dma */ +@@ -751,6 +857,9 @@ + + #if CONFIG_PROC_FS + remove_proc_entry ( PROC_NODE_NAME, NULL); ++#ifdef SA1100_USB_DEBUG ++ remove_proc_entry("sa1100_usb_debug",&proc_root); ++#endif + #endif + + sa1100_free_dma(usbd_info.dmach_rx); +@@ -769,6 +878,10 @@ + EXPORT_SYMBOL( sa1100_usb_get_string_descriptor ); + EXPORT_SYMBOL( sa1100_usb_kmalloc_string_descriptor ); + ++#ifdef SA1100_USB_DEBUG ++int sa1100_usb_debug=0; ++EXPORT_SYMBOL(sa1100_usb_debug); ++#endif + + module_init( usbctl_init ); + module_exit( usbctl_exit ); +--- linux-2.4.27/arch/arm/config.in~sa1100-usb ++++ linux-2.4.27/arch/arm/config.in +@@ -138,6 +138,9 @@ + dep_bool ' Yopy' CONFIG_SA1100_YOPY $CONFIG_ARCH_SA1100 + + dep_tristate 'SA1100 USB function support' CONFIG_SA1100_USB $CONFIG_ARCH_SA1100 ++if [ "$CONFIG_SA1100_USB" != "n" ]; then ++ bool ' Support for SA11x0 USB usb-hotplug' CONFIG_SA1100_USB_HOTPLUG ++fi + dep_tristate ' Support for SA11x0 USB network link function' CONFIG_SA1100_USB_NETLINK $CONFIG_SA1100_USB + dep_tristate ' Support for SA11x0 USB character device emulation' CONFIG_SA1100_USB_CHAR $CONFIG_SA1100_USB + diff --git a/recipes/linux/opensimpad/simpad-backlight-if.patch b/recipes/linux/opensimpad/simpad-backlight-if.patch new file mode 100644 index 0000000000..4e04afb5e9 --- /dev/null +++ b/recipes/linux/opensimpad/simpad-backlight-if.patch @@ -0,0 +1,102 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/drivers/video/mq200fb.c~simpad-backlight-if ++++ linux-2.4.27/drivers/video/mq200fb.c +@@ -82,6 +82,20 @@ + write: proc_write_reg + }; + ++#ifdef CONFIG_SA1100_SIMPAD ++ ++static ssize_t proc_read_light(struct file * file, char * buf, ++ size_t nbytes, loff_t *ppos); ++static ssize_t proc_write_light(struct file * file, const char * buffer, ++ size_t count, loff_t *ppos); ++ ++static struct file_operations proc_light_operations = { ++ read: proc_read_light, ++ write: proc_write_light ++}; ++#endif ++ ++ + typedef struct sa1110_reg_entry { + u32 phyaddr; + char* name; +@@ -622,6 +636,20 @@ + } + } + ++#ifdef CONFIG_SA1100_SIMPAD ++ entry = create_proc_entry("backlight", ++ S_IRWXU | S_IRWXG | S_IRWXO, ++ mq200dir); ++ if(entry) { ++ entry->proc_fops = &proc_light_operations; ++ } ++ else { ++ printk( KERN_ERR ++ "mq200fb: can't create /proc/" MQ200_DIRNAME ++ "/backlight\n"); ++ return(-ENOMEM); ++ } ++ #endif + + #ifdef MQ_SA1110 + +@@ -1879,7 +1907,7 @@ + static void writeBrightness(void *pMQMMIO, int brightness) + { + unsigned long dutyCycle, pwmcontrol; +- int MAX_BRIGHT_REG = 0x000000fc; /* int 254 */ ++ int MAX_BRIGHT_REG = 0x000000fe; /* int 254 */ + + if(brightness > MAX_BRIGHT_REG) + return; +@@ -1961,3 +1989,43 @@ + return (count+endp-buffer); + } + ++#ifdef CONFIG_SA1100_SIMPAD ++ ++#define SIMPAD_BACKLIGHT_MASK 0x00a10044 ++ ++static int proc_read_light(struct file * file, char * buf, ++ size_t nbytes, loff_t *ppos) ++{ ++ char outputbuf[15]; ++ int count; ++ u32 pwmctl; ++ if (*ppos>0) /* Assume reading completed in previous read*/ ++ return 0; ++ ++ pwmctl = *((volatile *) mq200_p2v(0x4be0e03c)); ++ pwmctl &= ~SIMPAD_BACKLIGHT_MASK; ++ pwmctl = pwmctl >> 8; ++ pwmctl = 254 - pwmctl; ++ ++ count = sprintf(outputbuf, "%d\n",pwmctl); ++ *ppos+=count; ++ if (count>nbytes) /* Assume output can be read at one time */ ++ return -EINVAL; ++ if (copy_to_user(buf, outputbuf, count)) ++ return -EFAULT; ++ return count; ++} ++ ++static ssize_t proc_write_light(struct file * file, const char * buffer, ++ size_t count, loff_t *ppos) ++{ ++ void * pMQMMIO = (void *) mqMmioAddr; ++ char *endp; ++ unsigned long newvalue = simple_strtoul(buffer,&endp,0); ++ if (newvalue > 254) ++ newvalue = 254; ++ writeBrightness(pMQMMIO,newvalue); ++ mq200_backlight(pMQMMIO,(int)newvalue); ++ return (count+endp-buffer); ++} ++#endif diff --git a/recipes/linux/opensimpad/simpad-proc-sys-board.patch b/recipes/linux/opensimpad/simpad-proc-sys-board.patch new file mode 100644 index 0000000000..e6a7e12e5e --- /dev/null +++ b/recipes/linux/opensimpad/simpad-proc-sys-board.patch @@ -0,0 +1,317 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/drivers/char/Makefile~simpad-proc-sys-board ++++ linux-2.4.27/drivers/char/Makefile +@@ -134,6 +134,9 @@ + ifeq ($(CONFIG_SA1100_CERF_CPLD),y) + KEYBD += cerf_keyb.o + endif ++ ifeq ($(CONFIG_SA1100_SIMPAD),y) ++ obj-$(CONFIG_SA1100_SIMPAD) += sysctl.o ++ endif + ifeq ($(CONFIG_ARCH_FORTUNET),y) + KEYMAP := defkeymap.o + endif +--- /dev/null ++++ linux-2.4.27/drivers/char/sysctl.c +@@ -0,0 +1,297 @@ ++/* ++ * /proc/sys/board - Interface to the SIMpad cs3 register ++ * ++ * (c) 2004 by Till Harbaum, BeeCon GmbH, <harbaum@beecon.de> ++ */ ++ ++#include <linux/module.h> ++#include <linux/init.h> ++#include <linux/errno.h> ++#include <linux/sysctl.h> ++#include <linux/crc32.h> ++#include <linux/delay.h> ++#include <linux/pm.h> ++ ++#include <asm/io.h> ++#include <asm/arch/simpad.h> ++#include <asm/uaccess.h> ++ ++extern long get_cs3_shadow(void); ++extern void set_cs3_bit(int value); ++extern void clear_cs3_bit(int value); ++ ++/* ++ * This is the number for the "board" entry in /proc/sys: ++ */ ++#define SIMPAD_SYSCTL 1312 ++ ++/* ++ * These are the numbers for the entries in /etc/sys/board ++ */ ++enum { ++ CTL_NAME=991, ++ CTL_CS3, // the complete latch ++ CTL_VCC_5V_EN, // For 5V PCMCIA ++ CTL_VCC_3V_EN, // FOR 3.3V PCMCIA ++ CTL_EN1, // This is only for EPROM's ++ CTL_EN0, // Both should be enable for 3.3V or 5V ++ CTL_DISPLAY_ON, ++ CTL_PCMCIA_BUFF_DIS, ++ CTL_MQ_RESET, ++ CTL_PCMCIA_RESET, ++ CTL_DECT_POWER_ON, ++ CTL_IRDA_SD, // Shutdown for powersave ++ CTL_RS232_ON, ++ CTL_SD_MEDIAQ, // Shutdown for powersave ++ CTL_LED2_ON, ++ CTL_IRDA_MODE, // Fast/Slow IrDA mode ++ CTL_ENABLE_5V, // Enable 5V circuit ++ CTL_RESET_SIMCARD ++}; ++ ++static const char simpad_board_name[] = "SIMpad"; ++static int dummy_int; ++static char dummy_str[80]; ++ ++static int ++simpad_sysctl_handler(ctl_table * ctl, int write, struct file *filp, ++ void *buffer, size_t * lenp) ++{ ++ int *valp = ctl->data; ++ int val; ++ int ret; ++ ++ // Update parameters from the real registers ++ switch (ctl->ctl_name) { ++ case CTL_CS3: ++ sprintf(dummy_str, "0x%04lx", get_cs3_shadow()); ++ return proc_dostring(ctl,write,filp,buffer,lenp); ++ break; ++ ++ // the 16 control bits of the cs3 register ++ case CTL_VCC_5V_EN: ++ case CTL_VCC_3V_EN: ++ case CTL_EN1: ++ case CTL_EN0: ++ case CTL_DISPLAY_ON: ++ case CTL_PCMCIA_BUFF_DIS: ++ case CTL_MQ_RESET: ++ case CTL_PCMCIA_RESET: ++ case CTL_DECT_POWER_ON: ++ case CTL_IRDA_SD: ++ case CTL_RS232_ON: ++ case CTL_SD_MEDIAQ: ++ case CTL_LED2_ON: ++ case CTL_IRDA_MODE: ++ case CTL_ENABLE_5V: ++ case CTL_RESET_SIMCARD: ++ *valp = (get_cs3_shadow() & ++ (1u << (ctl->ctl_name-CTL_VCC_5V_EN)))?1:0; ++ break; ++ ++ default: ++ // Just ignore unsupported parameters ++ break; ++ } ++ ++ // the strings are all handled now and ran onto a return; ++ ++ // Save old state ++ val = *valp; ++ ++ // Perform the generic integer operation ++ if ((ret = proc_dointvec(ctl, write, filp, buffer, lenp)) != 0) ++ return (ret); ++ ++ // Write changes out to the registers ++ if (write && *valp != val) { ++ ++ val = *valp; ++ switch (ctl->ctl_name) { ++ ++ // the 16 control bits of the cs3 register ++ case CTL_DISPLAY_ON: ++ case CTL_DECT_POWER_ON: ++ case CTL_IRDA_SD: ++ case CTL_SD_MEDIAQ: ++ case CTL_LED2_ON: ++ case CTL_IRDA_MODE: ++ case CTL_RESET_SIMCARD: ++ if (val) ++ set_cs3_bit(1u << (ctl->ctl_name-CTL_VCC_5V_EN)); ++ else ++ clear_cs3_bit(1u << (ctl->ctl_name-CTL_VCC_5V_EN)); ++ break; ++ ++ default: ++ // Just ignore unsupported parameters ++ break; ++ } ++ } ++ ++ return ret; ++} ++ ++#define PROC_RDONLY 0444 ++#define PROC_RDWR 0664 ++ ++static ctl_table simpad_table[] = { ++ { ++ procname: "sys_name", ++ ctl_name: CTL_NAME, ++ data: &simpad_board_name, ++ maxlen: sizeof(simpad_board_name), ++ proc_handler: &proc_dostring, ++ mode: PROC_RDONLY, ++ }, { ++ procname: "cs3", ++ ctl_name: CTL_CS3, ++ data: &dummy_str, ++ maxlen: sizeof(dummy_str), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDONLY, ++ }, { ++ procname: "vcc_5v_en", ++ ctl_name: CTL_VCC_5V_EN, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDONLY, ++ }, { ++ procname: "vcc_3v_en", ++ ctl_name: CTL_VCC_3V_EN, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDONLY, ++ }, { ++ procname: "en1", ++ ctl_name: CTL_EN1, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDONLY, ++ }, { ++ procname: "en0", ++ ctl_name: CTL_EN0, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDONLY, ++ }, { ++ procname: "display_on", ++ ctl_name: CTL_DISPLAY_ON, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDWR, ++ }, { ++ procname: "pcmcia_buff_dis", ++ ctl_name: CTL_PCMCIA_BUFF_DIS, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDONLY, ++ }, { ++ procname: "mq_reset", ++ ctl_name: CTL_MQ_RESET, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDONLY, ++ }, { ++ procname: "pcmcia_reset", ++ ctl_name: CTL_PCMCIA_RESET, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDONLY, ++ }, { ++ procname: "dect_power_on", ++ ctl_name: CTL_DECT_POWER_ON, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDWR, ++ }, { ++ procname: "irda_sd", ++ ctl_name: CTL_IRDA_SD, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDWR, ++ }, { ++ procname: "rs232_on", ++ ctl_name: CTL_RS232_ON, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDONLY, ++ }, { ++ procname: "sd_mediaq", ++ ctl_name: CTL_SD_MEDIAQ, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDWR, ++ }, { ++ procname: "led2_on", ++ ctl_name: CTL_LED2_ON, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDWR, ++ }, { ++ procname: "irda_mode", ++ ctl_name: CTL_IRDA_MODE, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDWR, ++ }, { ++ procname: "enable_5v", ++ ctl_name: CTL_ENABLE_5V, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDONLY, ++ }, { ++ procname: "reset_simcard", ++ ctl_name: CTL_RESET_SIMCARD, ++ data: &dummy_int, ++ maxlen: sizeof(int), ++ proc_handler: &simpad_sysctl_handler, ++ mode: PROC_RDWR, ++ }, ++ {0} ++ }; ++ ++static ctl_table simpad_root_table[] = { ++ {SIMPAD_SYSCTL, "board", NULL, 0, 0555, simpad_table}, ++ {0} ++ }; ++ ++ ++static struct ctl_table_header *simpad_table_header; ++ ++ ++static int __init simpad_sysctl_init(void) ++{ ++ simpad_table_header = register_sysctl_table(simpad_root_table, 0); ++ if (!simpad_table_header) ++ return -ENOMEM; ++ return 0; ++} ++ ++static void __exit simpad_sysctl_exit(void) ++{ ++ unregister_sysctl_table(simpad_table_header); ++} ++ ++ ++module_init(simpad_sysctl_init); ++module_exit(simpad_sysctl_exit); ++ ++MODULE_AUTHOR("Till Harbaum <harbaum@beecon.de>"); ++MODULE_DESCRIPTION("Implements /proc/sys/board"); ++MODULE_LICENSE("GPL"); diff --git a/recipes/linux/opensimpad/simpad-serial.patch b/recipes/linux/opensimpad/simpad-serial.patch new file mode 100644 index 0000000000..e54c682a06 --- /dev/null +++ b/recipes/linux/opensimpad/simpad-serial.patch @@ -0,0 +1,267 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/include/asm-arm/arch-sa1100/simpad.h~simpad-serial ++++ linux-2.4.27/include/asm-arm/arch-sa1100/simpad.h +@@ -16,7 +16,7 @@ + #error "include <asm/hardware.h> instead" + #endif + +-#define GPIO_UART1_RTS GPIO_GPIO14 ++#define GPIO_UART1_RTS GPIO_GPIO9 + #define GPIO_UART1_DTR GPIO_GPIO7 + #define GPIO_UART1_CTS GPIO_GPIO8 + #define GPIO_UART1_DCD GPIO_GPIO23 +@@ -31,12 +31,12 @@ + #define GPIO_POWER_BUTTON GPIO_GPIO0 + #define GPIO_UCB1300_IRQ GPIO_GPIO (22) /* UCB GPIO and touchscreen */ + +-#define IRQ_UART1_CTS IRQ_GPIO15 +-#define IRQ_UART1_DCD GPIO_GPIO23 +-#define IRQ_UART1_DSR GPIO_GPIO6 +-#define IRQ_UART3_CTS GPIO_GPIO13 +-#define IRQ_UART3_DCD GPIO_GPIO18 +-#define IRQ_UART3_DSR GPIO_GPIO17 ++#define IRQ_GPIO_UART1_CTS IRQ_GPIO8 ++#define IRQ_GPIO_UART1_DCD IRQ_GPIO23 ++#define IRQ_GPIO_UART1_DSR IRQ_GPIO6 ++#define IRQ_GPIO_UART3_CTS IRQ_GPIO13 ++#define IRQ_GPIO_UART3_DCD IRQ_GPIO18 ++#define IRQ_GPIO_UART3_DSR IRQ_GPIO17 + + #define IRQ_GPIO_UCB1300_IRQ IRQ_GPIO22 + #define IRQ_GPIO_POWER_BUTTON IRQ_GPIO0 +--- linux-2.4.27/arch/arm/mach-sa1100/simpad.c~simpad-serial ++++ linux-2.4.27/arch/arm/mach-sa1100/simpad.c +@@ -22,9 +22,11 @@ + + #include "generic.h" + ++#undef SIMPAD_UART_USE_IRQ // irq handling on CTS/DCD doesn't work yet ++ + long cs3_shadow; + +-long get_cs3_shadow() ++long get_cs3_shadow(void) + { + return cs3_shadow; + } +@@ -107,18 +109,170 @@ + LAST_DESC + }; + ++#define SER_INFO(fmt, arg...) printk(KERN_INFO fmt "\n" , ## arg) ++ ++static void simpad_uart_set_mctrl(struct uart_port *port, u_int mctrl) ++{ ++ if (port->mapbase == _Ser1UTCR0) { ++ /* internal serial port (ttySA1, DECT/Bluetooth) */ ++ if (mctrl & TIOCM_RTS) GPCR = GPIO_UART1_RTS; ++ else GPSR = GPIO_UART1_RTS; ++ ++ if (mctrl & TIOCM_DTR) GPCR = GPIO_UART1_DTR; ++ else GPSR = GPIO_UART1_DTR; ++ } ++ ++ else if (port->mapbase == _Ser3UTCR0) { ++ /* external serial port (ttySA0, RS232) */ ++ if (mctrl & TIOCM_RTS) GPCR = GPIO_UART3_RTS; ++ else GPSR = GPIO_UART3_RTS; ++ ++ if (mctrl & TIOCM_DTR) GPCR = GPIO_UART3_DTR; ++ else GPSR = GPIO_UART3_DTR; ++ } ++} ++ ++static u_int simpad_uart_get_mctrl(struct uart_port *port) ++{ ++ u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR; ++ ++ if (port->mapbase == _Ser1UTCR0) { ++ /* internal serial port (ttySA1, DECT/Bluetooth) */ ++ int gplr = GPLR; ++ if (gplr & GPIO_UART1_DCD) ret &= ~TIOCM_CD; ++ if (gplr & GPIO_UART1_CTS) ret &= ~TIOCM_CTS; ++ if (gplr & GPIO_UART1_DSR) ret &= ~TIOCM_DSR; ++ } ++ ++ else if (port->mapbase == _Ser3UTCR0) { ++ /* external serial port (ttySA0, RS232) */ ++ int gplr = GPLR; ++ if (gplr & GPIO_UART3_DCD) ret &= ~TIOCM_CD; ++ if (gplr & GPIO_UART3_CTS) ret &= ~TIOCM_CTS; ++ if (gplr & GPIO_UART3_DSR) ret &= ~TIOCM_DSR; ++ } ++ return ret; ++} ++ + static void simpad_uart_pm(struct uart_port *port, u_int state, u_int oldstate) + { +- if (port->mapbase == (u_int)&Ser1UTCR0) { ++ if (port->mapbase == (u_int)&Ser3UTCR0) { + if (state) + clear_cs3_bit(RS232_ON); + else + set_cs3_bit(RS232_ON); + } + } ++/* ++ * Enable/Disable wake up events for this serial port. ++ * Obviously, we only support this on the normal COM port. ++ */ ++static int simpad_uart_set_wake(struct uart_port *port, u_int enable) ++{ ++ int err = -EINVAL; ++ ++#if 0 // TODO: port management ++ if (port->mapbase == _Ser3UTCR0) { ++ if (enable) ++ PWER |= PWER_GPIO23 | PWER_GPIO25 ; /* DCD and CTS */ ++ else ++ PWER &= ~(PWER_GPIO23 | PWER_GPIO25); /* DCD and CTS */ ++ err = 0; ++ } ++#endif ++ ++ return err; ++} ++ ++#ifdef SIMPAD_UART_USE_IRQ ++static void simpad_uart1_dcd_intr(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ struct uart_port *port = dev_id; ++ /* Note: should only call this if something has changed */ ++ uart_handle_dcd_change(port, !(GPLR & GPIO_UART1_DCD)); ++} ++ ++static void simpad_uart1_cts_intr(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ struct uart_port *port = dev_id; ++ /* Note: should only call this if something has changed */ ++ uart_handle_cts_change(port, !(GPLR & GPIO_UART1_CTS)); ++} ++ ++static void simpad_uart3_dcd_intr(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ struct uart_port *port = dev_id; ++ /* Note: should only call this if something has changed */ ++ uart_handle_dcd_change(port, !(GPLR & GPIO_UART3_DCD)); ++} ++ ++static void simpad_uart3_cts_intr(int irq, void *dev_id, struct pt_regs *regs) ++{ ++ struct uart_port *port = dev_id; ++ /* Note: should only call this if something has changed */ ++ uart_handle_cts_change(port, !(GPLR & GPIO_UART3_CTS)); ++} ++#endif ++ ++static int simpad_uart_open(struct uart_port *port) ++{ ++ int ret = 0; ++#ifdef SIMPAD_UART_USE_IRQ ++ if (port->mapbase == _Ser1UTCR0) { ++ set_GPIO_IRQ_edge(GPIO_UART1_DCD|GPIO_UART1_CTS, ++ GPIO_BOTH_EDGES); ++ ++ ret = request_irq(IRQ_GPIO_UART1_DCD, simpad_uart1_dcd_intr, ++ 0, "UART1 DCD", port); ++ if (ret) ++ return ret; ++ ++ ret = request_irq(IRQ_GPIO_UART1_CTS, simpad_uart1_cts_intr, ++ 0, "UART1 CTS", port); ++ if (ret) ++ free_irq(IRQ_GPIO_UART1_DCD, port); ++ } ++ ++ else if (port->mapbase == _Ser3UTCR0) { ++ set_GPIO_IRQ_edge(GPIO_UART3_DCD|GPIO_UART3_CTS, ++ GPIO_BOTH_EDGES); ++ ++ ret = request_irq(IRQ_GPIO_UART3_DCD, simpad_uart3_dcd_intr, ++ 0, "UART3 DCD", port); ++ if (ret) ++ return ret; ++ ++ ret = request_irq(IRQ_GPIO_UART3_CTS, simpad_uart3_cts_intr, ++ 0, "UART3 CTS", port); ++ if (ret) ++ free_irq(IRQ_GPIO_UART3_DCD, port); ++ } ++#endif ++ return ret; ++} ++ ++static void simpad_uart_close(struct uart_port *port) ++{ ++#ifdef SIMPAD_UART_USE_IRQ ++ if (port->mapbase == _Ser1UTCR0) { ++ free_irq(IRQ_GPIO_UART1_DCD, port); ++ free_irq(IRQ_GPIO_UART1_CTS, port); ++ } ++ ++ else if (port->mapbase == _Ser3UTCR0) { ++ free_irq(IRQ_GPIO_UART3_DCD, port); ++ free_irq(IRQ_GPIO_UART3_CTS, port); ++ } ++#endif ++} + + static struct sa1100_port_fns simpad_port_fns __initdata = { +- .pm = simpad_uart_pm, ++ .set_mctrl = simpad_uart_set_mctrl, ++ .get_mctrl = simpad_uart_get_mctrl, ++ .pm = simpad_uart_pm, ++ .set_wake = simpad_uart_set_wake, ++ .open = simpad_uart_open, ++ .close = simpad_uart_close, + }; + + static void __init simpad_map_io(void) +@@ -129,13 +283,32 @@ + set_cs3_bit (EN1 | EN0 | LED2_ON | DISPLAY_ON | RS232_ON | + ENABLE_5V | nRESET_SIMCARD); + ++ sa1100_register_uart_fns(&simpad_port_fns); ++ + //It is only possible to register 3 UART in serial_sa1100.c + sa1100_register_uart(0, 3); + sa1100_register_uart(1, 1); + ++ // txd and rxd use their alternate function + GAFR |= (GPIO_UART_TXD | GPIO_UART_RXD); ++ ++ // the control lines are gpio ++ GAFR &= ~(GPIO_UART1_RTS | GPIO_UART1_CTS | GPIO_UART1_DCD); ++ GAFR &= ~(GPIO_UART1_DSR | GPIO_UART1_DTR); ++ GAFR &= ~(GPIO_UART3_RTS | GPIO_UART3_CTS | GPIO_UART3_DCD); ++ GAFR &= ~(GPIO_UART3_DSR | GPIO_UART3_DTR); ++ ++ // txd, rts and dtr are outputs + GPDR |= GPIO_UART_TXD; ++ GPDR |= GPIO_UART1_RTS | GPIO_UART3_RTS; ++ GPDR |= GPIO_UART1_DTR | GPIO_UART3_DTR; ++ ++ // cts, dcd, dsr and rxd are inputs ++ GPDR &= ~(GPIO_UART1_CTS | GPIO_UART3_CTS); ++ GPDR &= ~(GPIO_UART1_DCD | GPIO_UART3_DCD); ++ GPDR &= ~(GPIO_UART1_DSR | GPIO_UART3_DSR); + GPDR &= ~GPIO_UART_RXD; ++ + PPAR |= PPAR_UPR; + + set_GPIO_IRQ_edge(GPIO_UCB1300_IRQ, GPIO_RISING_EDGE); +--- linux-2.4.27/drivers/video/mq200fb.c~simpad-serial ++++ linux-2.4.27/drivers/video/mq200fb.c +@@ -672,7 +672,7 @@ + + #ifdef CONFIG_SA1100_SIMPAD + GPDR |= (1<<3); +- GAFR |= ~(1<<3); ++ GAFR &= ~(1<<3); + GPSR |= (1<<3); + #endif + diff --git a/recipes/linux/opensimpad/simpad-switches-input.patch b/recipes/linux/opensimpad/simpad-switches-input.patch new file mode 100644 index 0000000000..792b1af427 --- /dev/null +++ b/recipes/linux/opensimpad/simpad-switches-input.patch @@ -0,0 +1,131 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/drivers/misc/switches.h~simpad-switches-input ++++ linux-2.4.27/drivers/misc/switches.h +@@ -25,4 +25,14 @@ + extern int switches_ucb1x00_init(void); + extern void switches_ucb1x00_exit(void); + ++#ifdef CONFIG_SA1100_SIMPAD ++#define SIMPAD_KEY_SUSPEND 0x0002 ++#define SIMPAD_KEY_WWW 0x0008 ++#define SIMPAD_KEY_ENTER 0x0010 ++#define SIMPAD_KEY_UP 0x0020 ++#define SIMPAD_KEY_DOWN 0x0040 ++#define SIMPAD_KEY_LEFT 0x0080 ++#define SIMPAD_KEY_RIGHT 0x0100 ++#endif ++ + #endif /* !defined(_SWITCHES_H) */ +--- linux-2.4.27/drivers/misc/switches-core.c~simpad-switches-input ++++ linux-2.4.27/drivers/misc/switches-core.c +@@ -16,6 +16,9 @@ + * 11 September 2001 - UCB1200 driver framework support added. + * + * 19 December 2001 - separated out SA-1100 and UCB1x00 code. ++ * ++ * 3 July 2004 - Added generating of keyboard events. ++ * Florian Boor <florian@handhelds.org> + */ + + #include <linux/config.h> +@@ -30,7 +33,11 @@ + #include <linux/slab.h> + #include <linux/wait.h> + ++#include <linux/input.h> ++ + #include <asm/uaccess.h> ++#include <asm/hardware.h> ++#include <asm/keyboard.h> + + #include "switches.h" + +@@ -53,6 +60,19 @@ + DECLARE_WAIT_QUEUE_HEAD(switches_wait); + LIST_HEAD(switches_event_queue); + ++#ifdef CONFIG_INPUT ++static struct input_dev idev; ++ ++int ++dummy_k_translate(unsigned char scancode, unsigned char *keycode, char raw_mode) ++{ ++ *keycode = scancode; ++ return 1; ++} ++ ++extern int (*k_translate)(unsigned char, unsigned char *, char); ++ ++#endif + + static ssize_t switches_read(struct file *file, char *buffer, + size_t count, loff_t *pos) +@@ -148,6 +168,31 @@ + { + struct switches_action *action; + ++#ifdef CONFIG_INPUT ++ /* create input events, the events to send depends on the platform */ ++#ifdef CONFIG_SA1100_SIMPAD ++ if (machine_is_simpad()) { ++ if (SWITCHES_COUNT(mask) > 0) ++ { ++ if (mask->events[0] & SIMPAD_KEY_SUSPEND) ++ input_report_key(&idev, KEY_POWER, (mask->states[0] & SIMPAD_KEY_SUSPEND) ? 0 : 1); ++ if (mask->events[0] & SIMPAD_KEY_ENTER) ++ input_report_key(&idev, KEY_ENTER, (mask->states[0] & SIMPAD_KEY_ENTER) ? 1 : 0); ++ if (mask->events[0] & SIMPAD_KEY_UP) ++ input_report_key(&idev, KEY_UP, (mask->states[0] & SIMPAD_KEY_UP) ? 1 : 0); ++ if (mask->events[0] & SIMPAD_KEY_DOWN) ++ input_report_key(&idev, KEY_DOWN, (mask->states[0] & SIMPAD_KEY_DOWN) ? 1 : 0); ++ if (mask->events[0] & SIMPAD_KEY_LEFT) ++ input_report_key(&idev, KEY_LEFT, (mask->states[0] & SIMPAD_KEY_LEFT) ? 1 : 0); ++ if (mask->events[0] & SIMPAD_KEY_RIGHT) ++ input_report_key(&idev, KEY_RIGHT, (mask->states[0] & SIMPAD_KEY_RIGHT) ? 1 : 0); ++ if (mask->events[0] & SIMPAD_KEY_WWW) ++ input_report_key(&idev, KEY_F10, (mask->states[0] & SIMPAD_KEY_WWW) ? 1 : 0); ++ } ++ } ++#endif ++#endif ++ /* take care of switches device */ + if ((switches_users > 0) && (SWITCHES_COUNT(mask) > 0)) { + + if ((action = (struct switches_action *) +@@ -197,6 +242,21 @@ + return -EIO; + } + ++#ifdef CONFIG_INPUT ++ /* init input driver stuff */ ++ k_translate = dummy_k_translate; ++ idev.evbit[0] = BIT(EV_KEY); /* handle key events */ ++ ++ idev.keybit[LONG(KEY_POWER)] |= BIT(KEY_POWER); ++ idev.keybit[LONG(KEY_UP)] |= BIT(KEY_UP); ++ idev.keybit[LONG(KEY_DOWN)] |= BIT(KEY_DOWN); ++ idev.keybit[LONG(KEY_LEFT)] |= BIT(KEY_LEFT); ++ idev.keybit[LONG(KEY_RIGHT)] |= BIT(KEY_RIGHT); ++ idev.keybit[LONG(KEY_ENTER)] |= BIT(KEY_ENTER); ++ idev.keybit[LONG(KEY_F10)] |= BIT(KEY_F10); ++ ++ input_register_device(&idev); ++#endif + printk("Console switches initialized\n"); + + return 0; +@@ -214,6 +274,10 @@ + switches_ucb1x00_exit(); + #endif + ++#ifdef CONFIG_INPUT ++ input_unregister_device(&idev); ++#endif ++ + if (misc_deregister(&switches_misc) < 0) + printk(KERN_ERR "%s: unable to deregister misc device\n", + SWITCHES_NAME); diff --git a/recipes/linux/opensimpad/simpad-switches-input2.patch b/recipes/linux/opensimpad/simpad-switches-input2.patch new file mode 100644 index 0000000000..34529acabb --- /dev/null +++ b/recipes/linux/opensimpad/simpad-switches-input2.patch @@ -0,0 +1,41 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/drivers/misc/switches-core.c~simpad-switches-input2 ++++ linux-2.4.27/drivers/misc/switches-core.c +@@ -66,7 +66,32 @@ + int + dummy_k_translate(unsigned char scancode, unsigned char *keycode, char raw_mode) + { +- *keycode = scancode; ++ if (scancode == KEY_UP) ++ *keycode = 144; ++ else if (scancode == KEY_LEFT) ++ *keycode = 146; ++ else if (scancode == KEY_RIGHT) ++ *keycode = 151; ++ else if (scancode == KEY_DOWN) ++ *keycode = 161; ++ else if (scancode == 144) ++ *keycode = KEY_UP; ++ else if (scancode == 146) ++ *keycode = KEY_LEFT; ++ else if (scancode == 151) ++ *keycode = KEY_RIGHT; ++ else if (scancode == 161) ++ *keycode = KEY_DOWN; ++ else if (scancode == KEY_KP8) ++ *keycode = KEY_UP; ++ else if (scancode == KEY_KP4) ++ *keycode = KEY_LEFT; ++ else if (scancode == KEY_KP6) ++ *keycode = KEY_RIGHT; ++ else if (scancode == KEY_KP2) ++ *keycode = KEY_DOWN; ++ else ++ *keycode = scancode; + return 1; + } + diff --git a/recipes/linux/opensimpad/simpad-ts-noninput.patch b/recipes/linux/opensimpad/simpad-ts-noninput.patch new file mode 100644 index 0000000000..20a908ea8c --- /dev/null +++ b/recipes/linux/opensimpad/simpad-ts-noninput.patch @@ -0,0 +1,16 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/drivers/misc/ucb1x00-ts.c~simpad-ts-noninput ++++ linux-2.4.27/drivers/misc/ucb1x00-ts.c +@@ -35,7 +35,7 @@ + /* + * Define this if you want the UCB1x00 stuff to talk to the input layer + */ +-#ifdef CONFIG_INPUT ++#if defined(CONFIG_INPUT) && !defined(CONFIG_SA1100_SIMPAD) + #define USE_INPUT + #else + #undef USE_INPUT diff --git a/recipes/linux/opensimpad/sound-volume-reversed.patch b/recipes/linux/opensimpad/sound-volume-reversed.patch new file mode 100644 index 0000000000..495d8f9404 --- /dev/null +++ b/recipes/linux/opensimpad/sound-volume-reversed.patch @@ -0,0 +1,16 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/drivers/misc/ucb1x00-audio.c~sound-volume-reversed ++++ linux-2.4.27/drivers/misc/ucb1x00-audio.c +@@ -97,7 +97,7 @@ + ucba->output_level = gain | gain << 8; + ucba->mod_cnt++; + ucba->ctrl_b = (ucba->ctrl_b & 0xff00) | +- ((gain * 31) / 100); ++ (((100-gain) * 31) / 100); + ucb1x00_reg_write(ucba->ucb, UCB_AC_B, + ucba->ctrl_b); + ret = 0; diff --git a/recipes/linux/opensimpad/support-128mb-ram.patch b/recipes/linux/opensimpad/support-128mb-ram.patch new file mode 100644 index 0000000000..f0cde06b57 --- /dev/null +++ b/recipes/linux/opensimpad/support-128mb-ram.patch @@ -0,0 +1,35 @@ + +# +# Patch managed by http://www.holgerschurig.de/patcher.html +# + +--- linux-2.4.27/arch/arm/mach-sa1100/simpad.c~support-128mb-ram ++++ linux-2.4.27/arch/arm/mach-sa1100/simpad.c +@@ -83,11 +83,16 @@ + { + #ifdef CONFIG_SA1100_SIMPAD_SINUSPAD + SET_BANK( 0, 0xc0000000, 32*1024*1024 ); ++ mi->nr_banks = 1; + #else + SET_BANK( 0, 0xc0000000, 64*1024*1024 ); +-#endif + mi->nr_banks = 1; ++#endif + ++#ifdef CONFIG_SA1100_SIMPAD_128M ++ SET_BANK( 1, 0xc8000000, 64*1024*1024 ); ++ mi->nr_banks = 2; ++#endif + setup_ramdisk( 1, 0, 0, 8192 ); + setup_initrd( __phys_to_virt(0xc0800000), 4*1024*1024 ); + } +--- linux-2.4.27/arch/arm/config.in~support-128mb-ram ++++ linux-2.4.27/arch/arm/config.in +@@ -130,6 +130,7 @@ + dep_bool ' Simpad' CONFIG_SA1100_SIMPAD $CONFIG_ARCH_SA1100 + if [ "$CONFIG_SA1100_SIMPAD" = "y" ]; then + bool ' T-Sinus PAD' CONFIG_SA1100_SIMPAD_SINUSPAD ++ bool ' Simpad with 128Mb RAM' CONFIG_SA1100_SIMPAD_128M + fi + dep_bool ' Simputer' CONFIG_SA1100_SIMPUTER $CONFIG_ARCH_SA1100 + dep_bool ' Tulsa' CONFIG_SA1100_PFS168 $CONFIG_ARCH_SA1100 |