Re: Some coordination
Free The Cube <[email protected]>
| Newsgroups | gmane.linux.ports.game-cube.devel |
|---|---|
| Message-ID | <[email protected]> |
Michael Steil wrote: > On 23.01.2004, at 09:49, Free The Cube wrote: > >> You're right :) !!!! But the "temporary" driver is written :), it need >> more tests (it's a port of the GCLIB driver so it should work >> correclty (i hope) :) >> I will work on the SI driver... > > > Great. Jut send a kernel patch (preferably 2.6.1) to the mailing list > and we'll put it in the CVS for everyone to see it. > ...and you need an SF CVS account yourself then. > I can't send you a patch against 2.6.1, I'm at my work office ;) (no kernel sources, and can't spend time to download, test, ...) but I can send you the source file tested with linux 2.4.XX :) ! In my version, there are 2 parts : - the GCPAD driver - some functions (not finished) to test it with my 86 box... I removed the last one in the attached file. We still must adjust some values such as 'gcpad[i].dev.absmin' 'gcpad[i].dev.absmax' !!! If i remember correctly, the trigger values go from -32767 to 32768, it is not really what we want (0 to 32768). This driver (if it works :) ) is not really good : - the active loop wastes CPU time, even if i didn't feel this into my x86 box. - it doesn't use the SI layer - and the worst : it is not tested :) ! let us not be so pessimistic : it uses the standart input layer :D... Free The Cube.
gcpad.c
(text/x-csrc, 8.4 KB)
/* * Based on GCLIB (Free GameCube SDK Libraries) by costis * GC_PAD.c by CrowTRobo and tmbinc */ /* * Based on the PSX gamepad driver for Linux * gamecon.c Copyright (c) 1999-2001 Vojtech Pavlik */ /* * Ported by Free The Cube <[email protected]> * GameCube joystick device driver for the input driver suite. */ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Should you need to contact me, the author, you can do so either by * e-mail - mail your message to <[email protected]> */ #include <linux/config.h> //CONFIG_* #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> //module_init(), module_exit() #include <linux/ioport.h> //struct resource #include <linux/errno.h> //EBUSY #include <linux/delay.h> //udelay() #include <linux/slab.h> //kmalloc(), kfree() #include <linux/input.h> #ifdef CONFIG_SMP #define __SMP__ #endif //CONFIG_SMP #define GCPAD_LEFT 0x0001 #define GCPAD_RIGHT 0x0002 #define GCPAD_DOWN 0x0004 #define GCPAD_UP 0x0008 #define GCPAD_Z 0x0010 #define GCPAD_R 0x0020 #define GCPAD_L 0x0040 #define GCPAD_A 0x0100 #define GCPAD_B 0x0200 #define GCPAD_X 0x0400 #define GCPAD_Y 0x0800 #define GCPAD_START 0x1000 #define GCPAD_SI_BASE (0xCC006400) #define GCPAD_CHANNEL(chan) (GCPAD_SI_BASE+(chan*12)) #define GCPAD_REFRESH_TIME HZ/50 MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("GameCube joystick device driver"); MODULE_SUPPORTED_DEVICE("Simple controller"); static void gcpad_timer(unsigned long private); static int gcpad_open(struct input_dev *dev); static void gcpad_close(struct input_dev *dev); struct gcpad_dev { struct input_dev dev; short number; struct timer_list timer; int count; }; static struct gcpad_dev *gcpad; static short gcpad_btn[] = { BTN_A, BTN_B, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START }; static short gcpad_abs[] = { ABS_X, ABS_Y, // Main joystick ABS_RX, ABS_RY, // C-stick ABS_HAT0X, ABS_HAT0Y, // Trigger left and right ABS_HAT1X ,ABS_HAT1Y // Digital axes }; // Memory map for joypad (TODO : confirmations needed !) : // Lower = 0xCC006400 // Upper = 0xCC006480 static struct resource gcpad_resource = { "gcpad", 0xCC006400, 0xCC006480, IORESOURCE_MEM|IORESOURCE_BUSY }; static int __init gcpad_init(void) { int i,j; // Get the memory where pads are mapped if(request_resource(&iomem_resource, &gcpad_resource) < 0) { printk(KERN_WARNING "gcpad : resource busy\n"); return -EBUSY; } gcpad = kmalloc(4*sizeof(struct gcpad_dev), GFP_KERNEL); if(gcpad == NULL) return -ENOMEM; memset(gcpad, 0, 4*sizeof(struct gcpad_dev)); // For each pads for (i = 0; i < 4; i++) { // Initalize callbacks and private data. gcpad[i].number = i; gcpad[i].dev.private = &gcpad[i]; gcpad[i].dev.open = gcpad_open; gcpad[i].dev.close = gcpad_close; // Declare avaible events. set_bit(EV_KEY, gcpad[i].dev.evbit); set_bit(EV_ABS, gcpad[i].dev.evbit); // Declare avaible buttons. for(j = 0; j < 8; j++) set_bit(gcpad_btn[j], gcpad[i].dev.keybit); // Initialize and declare avaible axes. for(j = 0; j < 8; j++) { set_bit(gcpad_abs[j], gcpad[i].dev.absbit); switch(j) { case 0: case 1: // Main joystick case 2: case 3 : // C-stick gcpad[i].dev.absmin[gcpad_abs[j]] = -128; gcpad[i].dev.absmax[gcpad_abs[j]] = 127; gcpad[i].dev.absfuzz[gcpad_abs[j]] = 0; gcpad[i].dev.absflat[gcpad_abs[j]] = 0; break; case 4: case 5: // Trigger left and right gcpad[i].dev.absmin[gcpad_abs[j]] = 0; gcpad[i].dev.absmax[gcpad_abs[j]] = 255; gcpad[i].dev.absfuzz[gcpad_abs[j]] = 0; gcpad[i].dev.absflat[gcpad_abs[j]] = 0; break; case 6: case 7: //Digital axes gcpad[i].dev.absmin[gcpad_abs[j]] = -1; gcpad[i].dev.absmax[gcpad_abs[j]] = 1; gcpad[i].dev.absfuzz[gcpad_abs[j]] = 0; gcpad[i].dev.absflat[gcpad_abs[j]] = 0; break; } } input_register_device(&gcpad[i].dev); init_timer(&gcpad[i].timer); gcpad[i].timer.data = (long)&gcpad[i]; gcpad[i].timer.function = gcpad_timer; } // Taken directly from tmbinc's IPL replacement code. // Initializes all controllers! // 32bits access *(volatile unsigned long*)0xCC006430 = 0x00000000; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006430 = 0x00f70200; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006480 = 0x00000000; *(volatile unsigned long*)0xCC006434 = 0xc0010301; *(volatile unsigned long*)0xCC006438 = 0x00000000; (void)*(volatile unsigned long*)0xCC006434; *(volatile unsigned long*)0xCC006430 |= 0xF0; // enable all four controller ports *(volatile unsigned long*)0xCC006400 = 0x00400300; *(volatile unsigned long*)0xCC00640C = 0x00400300; *(volatile unsigned long*)0xCC006418 = 0x00400300; *(volatile unsigned long*)0xCC006424 = 0x00400300; udelay(1000); *(volatile unsigned long*)0xCC006430 = 0x00000000; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006430 = 0x00f70200; *(volatile unsigned long*)0xCC006438 = 0x80000000; *(volatile unsigned long*)0xCC006480 = 0x00000000; *(volatile unsigned long*)0xCC006434 = 0xc0010301; *(volatile unsigned long*)0xCC006438 = 0x00000000; (void)*(volatile unsigned long*)0xCC006434; *(volatile unsigned long*)0xCC006430 |= 0xF0; // enable all four controller ports *(volatile unsigned long*)0xCC006400 = 0x00400300; *(volatile unsigned long*)0xCC00640C = 0x00400300; *(volatile unsigned long*)0xCC006418 = 0x00400300; *(volatile unsigned long*)0xCC006424 = 0x00400300; return 0; } static void __exit gcpad_cleanup(void) { int i; for (i = 0; i < 4; i++) input_unregister_device(&gcpad[i].dev); kfree(gcpad); release_resource(&gcpad_resource); return; } static void gcpad_timer(unsigned long private) { struct gcpad_dev *pad = (void *) private; unsigned long pdata; short chan = pad->number; u16 button; // TODO : Does it need a delay between two read ? // Get the button and control stick values pdata = *(volatile unsigned long *)(GCPAD_CHANNEL(chan)+4); button = pdata >> 16; if(button & GCPAD_LEFT) input_report_abs(&pad->dev, ABS_HAT0X, -1); if(button & GCPAD_RIGHT) input_report_abs(&pad->dev, ABS_HAT0X, 1); if(button & GCPAD_UP) input_report_abs(&pad->dev, ABS_HAT0Y, 1); if(button & GCPAD_DOWN) input_report_abs(&pad->dev, ABS_HAT0Y, -1); input_report_key(&pad->dev, BTN_TL, button & GCPAD_L); input_report_key(&pad->dev, BTN_TR, button & GCPAD_R); input_report_key(&pad->dev, BTN_A, button & GCPAD_A); input_report_key(&pad->dev, BTN_B, button & GCPAD_B); input_report_key(&pad->dev, BTN_X, button & GCPAD_X); input_report_key(&pad->dev, BTN_Y, button & GCPAD_Y); input_report_key(&pad->dev, BTN_Z, button & GCPAD_Z); input_report_key(&pad->dev, BTN_START, button & GCPAD_START); input_report_abs(&pad->dev, ABS_X, 128 + ((pdata >> 8) & 0xff)); input_report_abs(&pad->dev, ABS_Y, 128 - (pdata & 0xff)); // Get the c-stick and trigger values pdata = *(volatile unsigned long *)(GCPAD_CHANNEL(chan)+8); input_report_abs(&pad->dev, ABS_RX, 128 + (pdata >> 24)); input_report_abs(&pad->dev, ABS_RX, 128 - ((pdata >> 16) & 0xff)); input_report_abs(&pad->dev, ABS_HAT0X, (pdata >> 8) & 0xff); input_report_abs(&pad->dev, ABS_HAT0Y, pdata & 0xff); mod_timer(&pad->timer, jiffies + GCPAD_REFRESH_TIME); } static int gcpad_open(struct input_dev *dev) { struct gcpad_dev *pad = dev->private; if (!pad->count++) mod_timer(&pad->timer, jiffies + GCPAD_REFRESH_TIME); return 0; } static void gcpad_close(struct input_dev *dev) { struct gcpad_dev *pad = dev->private; if (!--pad->count) del_timer(&pad->timer); } module_init(gcpad_init); module_exit(gcpad_cleanup);
Makefile
(application/x-java-vm, 559 B) - not displayed