LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware
User Name
Password
Linux - Hardware This forum is for Hardware issues.
Having trouble installing a piece of hardware? Want to know if that peripheral is compatible with Linux?

Notices


Reply
  Search this Thread
Old 07-01-2007, 08:32 PM   #1
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,202
Blog Entries: 3

Rep: Reputation: 62
Sega Genesis 6-button Joystick with DirectPad Pro interface.


Hello!

I'm trying to connect 6-button joystick from Sega Mega Drive on Slackware 11 linux/2.6.17.13 kernel. Joystick is connected to parallel port usin this scheme, taken from here. The problem is that while there is a native support for this kind of joystick, db9 module in linux kernel needs a different interface - this one. As a result, I can easily insert module into kernel, but joystick won' work.
I did not find any info about supporting DirectPad in kernel sources.

It could be easy to hack db9.c and modify certain bits sent to parallel port, but it looks like DirectPad needs to write into "data" pins and I didn't yet find out how can I do it. (standard interface reads from data pins and writes at least to strobe pin, and it looks like writing into "data" pins requires some other technique)

So, the question is:
Is there a patch/driver that provides support for such interface in 2.6.17.13 kernel without rebuilding joystic interface using soldering iron?

Thanks.
 
Old 07-02-2007, 12:48 PM   #2
b0uncer
LQ Guru
 
Registered: Aug 2003
Distribution: CentOS, OS X
Posts: 5,131

Rep: Reputation: Disabled
I've been looking for an answer for some time now too, haven't found yet. Not that I would have spent endless hours for that, but still. I'm interested in the solution too, hope you'll find an answer if I don't.
 
Old 07-02-2007, 01:09 PM   #3
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,202

Original Poster
Blog Entries: 3

Rep: Reputation: 62
I've tried to modify drivers/input/joystic/db9.c file to figure out correct values to pass into parallel port, but it looks like to use DirectPad Pro interface I need another method for writing data into serial port - I've tried to modify DB9_NORMAL and DB9_NOSELECT values to make them trigger joystick input pin used for synchronization. I've tried setting DB9_NORMAL to 0xFF and DB9_NOSELECT to 0xF0 and 0x0F - because DirectPad Pro interface has 6 serial port pins connected to +5v pin, one of the values was supposed to trigger select line while keeping joystic's power supply alive. since there is only 8 bits to read pressing buttons on joystic should have triggered some buttons which db9 understands. Unfortunately, this didn't work, nothing happened, and pressing any button didn't trigger anything in both casses. It looks like I need another technique to write into parallel port.

This joystick was working with this interface WindowsXP using PPJoy driver, so there should be no problems with the joystic or interface.
---
I've found linux-joystick mailing list, and sent same questions there.

Quote:
Originally Posted by b0uncer
I've been looking for an answer for some time now too, haven't found yet. Not that I would have spent endless hours for that, but still. I'm interested in the solution too, hope you'll find an answer if I don't.
Ok. As a last resort I can always try to rebuild an interface...
 
Old 07-04-2007, 08:30 AM   #4
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,202

Original Poster
Blog Entries: 3

Rep: Reputation: 62
Well, it looks like linux-joystick mailing list is dead. I'm only getting spam through it, nothing more..

I've asked for assistance (writing to parallel port) on local programming forums.
 
Old 07-13-2007, 07:29 AM   #5
archtoad6
Senior Member
 
Registered: Oct 2004
Location: Houston, TX (usa)
Distribution: MEPIS, Debian, Knoppix,
Posts: 4,727
Blog Entries: 15

Rep: Reputation: 234Reputation: 234Reputation: 234
See next, earlier edit caused a duplication of this post.

Last edited by archtoad6; 07-28-2007 at 11:07 AM.
 
Old 07-13-2007, 07:32 AM   #6
archtoad6
Senior Member
 
Registered: Oct 2004
Location: Houston, TX (usa)
Distribution: MEPIS, Debian, Knoppix,
Posts: 4,727
Blog Entries: 15

Rep: Reputation: 234Reputation: 234Reputation: 234
1st, try not to re-build the interface. The very worst you should have to do is make an adapter. I think is was Radio Shack that used to sell a DIY kit. It a male/female pair of DB25's connected by a really simple blank circuit board. It came w/ a bunch of short, solderable jumper wires & then went into a black case. The whole thing was maybe 2.5 x 1.5 x .6 inches. I think it looked something like this, as best as I do ASCII art:
Code:
  |               |
==|-o-o-o   o-o-o-|==
==|-o-o-o   o-o-o-|==
==|-o-o-o   o-o-o-|==
==|-o-o-o   o-o-o-|==
==|-o-o-o   o-o-o-|==
 . . .
The idea was to be able to connect any pin to any other pin(s) w/ complete flexibility. I used one to make a "Laplink cable" conversion adapter. A sort of parallel null modem cable.

BTW, I doubt that RS stills sells these, & I have no idea who might.


Laplink & its competitors were able to do the kind of writing to the parallel port that you want to do.

Check out these links:
http://en.wikipedia.org/wiki/IEEE_1284
http://en.wikipedia.org/wiki/Laplink_cable

From the 2nd:
This probably means that there are Linux drivers somewhere that you can either use or modify.

Or I have completely misunderstood your problem.

Edit: One other thing -- please don't be insulted, but have you got the BIOS parallel port settings correct?
 
Old 07-13-2007, 07:44 AM   #7
archtoad6
Senior Member
 
Registered: Oct 2004
Location: Houston, TX (usa)
Distribution: MEPIS, Debian, Knoppix,
Posts: 4,727
Blog Entries: 15

Rep: Reputation: 234Reputation: 234Reputation: 234
After thought

I did this:
http://www.google.com/search?q=site%...p.org+parallel

& found this:
http://www.tldp.org/HOWTO/NET3-4-HOWTO-7.html

Perhaps there are some helpful hints there in spite of its age.
 
Old 07-13-2007, 07:55 AM   #8
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,202

Original Poster
Blog Entries: 3

Rep: Reputation: 62
Quote:
Originally Posted by archtoad6
1st, try not to re-build the interface. The very worst you should have to do is make an adapter.
Well, I have some trouble with english names for electronic parts, but I hope you'll understand.

Current "interface" is really an adapter, that i've made mysefl - it is just two connectors (or is it called "socket"?) - one for sega Genesis and one for parallel port, connected with wires and several diodes - so I'm able to unplug joystick from this "adapter". The whole thing is small enough and could have been placed inside the cases of those connectors, if I had more patience. I could have made another adapter like this one but this is painful - I had real trouble with soldering wires with those small pins (?) on the back side of connectors, and I'm not in the mood to go through that again. So I just want to remake driver for this thing - because I'm better programmer than repairman or whatever.

Quote:
Originally Posted by archtoad6
I think is was Radio Shack that used to sell a DIY kit. It a male/female pair of DB25's connected by a really simple blank circuit board.
nice Idea, but I've never seen something like this in the shops in my town.

Quote:
Originally Posted by archtoad6
Laplink & its competitors were able to do the kind of writing to the parallel port that you want to do.

Check out these links:
http://en.wikipedia.org/wiki/IEEE_1284
http://en.wikipedia.org/wiki/Laplink_cable

From the 2nd:
This probably means that there are Linux drivers somewhere that you can either use or modify.
Hmm. Thanks, I'll check this.

Quote:
Originally Posted by archtoad6
Or I have completely misunderstood your problem.
No, everything is fine. I just don't know how to write into certain pins because I don't have a sample code.I remember that there were two modes of operation for parallel port, and one of them was more advanced (and allowed to write into the pins I want to use). It looks like db9.c uses "simple" mode and I need "advanced" one...

Last edited by ErV; 07-13-2007 at 08:09 AM.
 
Old 07-13-2007, 08:06 AM   #9
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,202

Original Poster
Blog Entries: 3

Rep: Reputation: 62
Quote:
Originally Posted by archtoad6
I did this:
http://www.google.com/search?q=site%...p.org+parallel

& found this:
http://www.tldp.org/HOWTO/NET3-4-HOWTO-7.html

Perhaps there are some helpful hints there in spite of its age.
Well, thanks. I was also able to find this: http://www.gmonline.demon.co.uk/cscene/CS4/CS4-02.html. It can be helpful, too.

Ok, I'll check that later (perhaps during todays evening), and then report the result.
 
Old 07-13-2007, 08:45 AM   #10
archtoad6
Senior Member
 
Registered: Oct 2004
Location: Houston, TX (usa)
Distribution: MEPIS, Debian, Knoppix,
Posts: 4,727
Blog Entries: 15

Rep: Reputation: 234Reputation: 234Reputation: 234
Good Luck, & definitely post the results.

Just no long, or especially wide, C code -- I don't read it & Konqueror doesn't handle wide "Code:" blocks from LQ gracefully -- please.
 
Old 01-04-2008, 05:46 AM   #11
archtoad6
Senior Member
 
Registered: Oct 2004
Location: Houston, TX (usa)
Distribution: MEPIS, Debian, Knoppix,
Posts: 4,727
Blog Entries: 15

Rep: Reputation: 234Reputation: 234Reputation: 234
Here I am, just dropped to admire my own art, & I noticed you never posted any results.

How about it -- How did it go? What happened?
 
Old 01-04-2008, 01:01 PM   #12
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,202

Original Poster
Blog Entries: 3

Rep: Reputation: 62
Quote:
Originally Posted by archtoad6 View Post
Here I am, just dropped to admire my own art, & I noticed you never posted any results.

How about it -- How did it go? What happened?
Well, I'm ashamed to say, but I've managed somehow to never start fixing the problem until I've recieved notification about your post today. :-\

After that I've finally sat down and was able to create a draft version version of fixed db9.c with dpadpro interface (file is attached to message). That took just 30 minutes. Well, it just proves that "never plan to do tomorrow something you can do right now".

Right now joystick responds (in control center in KDE), but all controls are messed up (so it is unusable, but you at least can see it 'kind of' works). to use new interface you'll need to insmod db9.ko with parameters dev=0,13 .

You can either fix constants used in new db9.c yourself, or you can wait until I'll do it. Since right now i'm really angry about how much time I've spent planning to "fix that thing later", I'll most likely fix it pretty soon. (certainly it won't take another six months!).

the db9.c is taken from 2.5.21.5-smp kernel source for slackware 12.

/usr/src/linux/drivers/input/joystick/db9.c:
Code:
/* --comments removed to make code fit ---
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/parport.h>
#include <linux/input.h>
#include <linux/mutex.h>

MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Atari, Amstrad, Commodore, Amiga, Sega, etc. joystick driver");
MODULE_LICENSE("GPL");

struct db9_config {
	int args[2];
	int nargs;
};

#define DB9_MAX_PORTS		3
static struct db9_config db9[DB9_MAX_PORTS] __initdata;

module_param_array_named(dev, db9[0].args, int, &db9[0].nargs, 0);
MODULE_PARM_DESC(dev, "Describes first attached device (<parport#>,<type>)");
module_param_array_named(dev2, db9[1].args, int, &db9[0].nargs, 0);
MODULE_PARM_DESC(dev2, "Describes second attached device (<parport#>,<type>)");
module_param_array_named(dev3, db9[2].args, int, &db9[2].nargs, 0);
MODULE_PARM_DESC(dev3, "Describes third attached device (<parport#>,<type>)");

#define DB9_ARG_PARPORT		0
#define DB9_ARG_MODE		1

#define DB9_MULTI_STICK		0x01
#define DB9_MULTI2_STICK	0x02
#define DB9_GENESIS_PAD		0x03
#define DB9_GENESIS5_PAD	0x05
#define DB9_GENESIS6_PAD	0x06
#define DB9_SATURN_PAD		0x07
#define DB9_MULTI_0802		0x08
#define DB9_MULTI_0802_2	0x09
#define DB9_CD32_PAD		0x0A
#define DB9_SATURN_DPP		0x0B
#define DB9_SATURN_DPP_2	0x0C
#define DB9_GENESIS6_DPADPRO	0x0D
#define DB9_MAX_PAD		0x0E

#define DB9_UP			0x01
#define DB9_DOWN		0x02
#define DB9_LEFT		0x04
#define DB9_RIGHT		0x08
#define DB9_FIRE1		0x10
#define DB9_FIRE2		0x20
#define DB9_FIRE3		0x40
#define DB9_FIRE4		0x80

#define DB9_DPADPRO_UP		0x01
#define DB9_DPADPRO_DOWN	0x02
#define DB9_DPADPRO_LEFT	0x04
#define DB9_DPADPRO_RIGHT	0x08
#define DB9_DPADPRO_FIRE1	0x10
#define DB9_DPADPRO_FIRE2	0x20
#define DB9_DPADPRO_FIRE3	0x40
#define DB9_DPADPRO_FIRE4	0x80

#define DB9_GENESISDPADPRO_UP		PARPORT_CONTROL_STROBE
#define DB9_GENESISDPADPRO_DOWN		PARPORT_CONTROL_AUTOFD
#define DB9_GENESISDPADPRO_LEFT		PARPORT_STATUS_ACK
#define DB9_GENESISDPADPRO_RIGHT	PARPORT_STATUS_BUSY
#define DB9_GENESISDPADPRO_FIRE1	PARPORT_STATUS_PAPEROUT
#define DB9_GENESISDPADPRO_FIRE2	PARPORT_STATUS_SELECT
#define DB9_GENESISDPADPRO_FIRE3	0x40
#define DB9_GENESISDPADPRO_FIRE4	0x80

#define DB9_GENESISDPADPRO_NORMAL	0xFF
#define DB9_GENESISDPADPRO_NOSELECT	0xFE

#define DB9_NORMAL		0x0a
#define DB9_NOSELECT		0x08

#define DB9_GENESIS6_DELAY	14
#define DB9_REFRESH_TIME	HZ/100

#define DB9_MAX_DEVICES		2

struct db9_mode_data {
	const char *name;
	const short *buttons;
	int n_buttons;
	int n_pads;
	int n_axis;
	int bidirectional;
	int reverse;
};

struct db9 {
	struct input_dev *dev[DB9_MAX_DEVICES];
	struct timer_list timer;
	struct pardevice *pd;
	int mode;
	int used;
	struct mutex mutex;
	char phys[DB9_MAX_DEVICES][32];
};

static struct db9 *db9_base[3];

static const short db9_multi_btn[] = { BTN_TRIGGER, BTN_THUMB };
static const short db9_genesis_btn[] = { BTN_START, BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_MODE };
static const short db9_cd32_btn[] = { BTN_A, BTN_B, BTN_C, BTN_X, BTN_Y, BTN_Z, BTN_TL, BTN_TR, BTN_START };
static const short db9_abs[] = { ABS_X, ABS_Y, ABS_RX, ABS_RY, ABS_RZ, ABS_Z, ABS_HAT0X, ABS_HAT0Y, ABS_HAT1X, ABS_HAT1Y };

static const struct db9_mode_data db9_modes[] = {
	{ NULL,					 NULL,		  0,  0,  0,  0,  0 },
	{ "Multisystem joystick",		 db9_multi_btn,	  1,  1,  2,  1,  1 },
	{ "Multisystem joystick (2 fire)",	 db9_multi_btn,	  2,  1,  2,  1,  1 },
	{ "Genesis pad",			 db9_genesis_btn, 4,  1,  2,  1,  1 },
	{ NULL,					 NULL,		  0,  0,  0,  0,  0 },
	{ "Genesis 5 pad",			 db9_genesis_btn, 6,  1,  2,  1,  1 },
	{ "Genesis 6 pad",			 db9_genesis_btn, 8,  1,  2,  1,  1 },
	{ "Saturn pad",				 db9_cd32_btn,	  9,  6,  7,  0,  1 },
	{ "Multisystem (0.8.0.2) joystick",	 db9_multi_btn,	  1,  1,  2,  1,  1 },
	{ "Multisystem (0.8.0.2-dual) joystick", db9_multi_btn,	  1,  2,  2,  1,  1 },
	{ "Amiga CD-32 pad",			 db9_cd32_btn,	  7,  1,  2,  1,  1 },
	{ "Saturn dpp",				 db9_cd32_btn,	  9,  6,  7,  0,  0 },
	{ "Saturn dpp dual",			 db9_cd32_btn,	  9,  12, 7,  0,  0 },
	{ "Genesis 6 DirectPadPro pad",		 db9_genesis_btn, 8,  1,  2,  1,  1 },
};

/*
 * Saturn controllers
 */
#define DB9_SATURN_DELAY 300
static const int db9_saturn_byte[] = { 1, 1, 1, 2, 2, 2, 2, 2, 1 };
static const unsigned char db9_saturn_mask[] = { 0x04, 0x01, 0x02, 0x40, 0x20, 0x10, 0x08, 0x80, 0x08 };

/*
 * db9_saturn_write_sub() writes 2 bit data.
 */
static void db9_saturn_write_sub(struct parport *port, int type, unsigned char data, int powered, int pwr_sub)
{
	unsigned char c;

	switch (type) {
	case 1: /* DPP1 */
		c = 0x80 | 0x30 | (powered ? 0x08 : 0) | (pwr_sub ? 0x04 : 0) | data;
		parport_write_data(port, c);
		break;
	case 2: /* DPP2 */
		c = 0x40 | data << 4 | (powered ? 0x08 : 0) | (pwr_sub ? 0x04 : 0) | 0x03;
		parport_write_data(port, c);
		break;
	case 0:	/* DB9 */
		c = ((((data & 2) ? 2 : 0) | ((data & 1) ? 4 : 0)) ^ 0x02) | !powered;
		parport_write_control(port, c);
		break;
	}
}

/*
 * gc_saturn_read_sub() reads 4 bit data.
 */
static unsigned char db9_saturn_read_sub(struct parport *port, int type)
{
	unsigned char data;

	if (type) {
		/* DPP */
		data = parport_read_status(port) ^ 0x80;
		return (data & 0x80 ? 1 : 0) | (data & 0x40 ? 2 : 0)
		     | (data & 0x20 ? 4 : 0) | (data & 0x10 ? 8 : 0);
	} else {
		/* DB9 */
		data = parport_read_data(port) & 0x0f;
		return (data & 0x8 ? 1 : 0) | (data & 0x4 ? 2 : 0)
		     | (data & 0x2 ? 4 : 0) | (data & 0x1 ? 8 : 0);
	}
}

/*
 * db9_saturn_read_analog() sends clock and reads 8 bit data.
 */
static unsigned char db9_saturn_read_analog(struct parport *port, int type, int powered)
{
	unsigned char data;

	db9_saturn_write_sub(port, type, 0, powered, 0);
	udelay(DB9_SATURN_DELAY);
	data = db9_saturn_read_sub(port, type) << 4;
	db9_saturn_write_sub(port, type, 2, powered, 0);
	udelay(DB9_SATURN_DELAY);
	data |= db9_saturn_read_sub(port, type);
	return data;
}

/*
 * db9_saturn_read_packet() reads whole saturn packet at connector
 * and returns device identifier code.
 */
static unsigned char db9_saturn_read_packet(struct parport *port, unsigned char *data, int type, int powered)
{
	int i, j;
	unsigned char tmp;

	db9_saturn_write_sub(port, type, 3, powered, 0);
	data[0] = db9_saturn_read_sub(port, type);
	switch (data[0] & 0x0f) {
	case 0xf:
		/* 1111  no pad */
		return data[0] = 0xff;
	case 0x4: case 0x4 | 0x8:
		/* ?100 : digital controller */
		db9_saturn_write_sub(port, type, 0, powered, 1);
		data[2] = db9_saturn_read_sub(port, type) << 4;
		db9_saturn_write_sub(port, type, 2, powered, 1);
		data[1] = db9_saturn_read_sub(port, type) << 4;
		db9_saturn_write_sub(port, type, 1, powered, 1);
		data[1] |= db9_saturn_read_sub(port, type);
		db9_saturn_write_sub(port, type, 3, powered, 1);
		/* data[2] |= db9_saturn_read_sub(port, type); */
		data[2] |= data[0];
		return data[0] = 0x02;
	case 0x1:
		/* 0001 : analog controller or multitap */
		db9_saturn_write_sub(port, type, 2, powered, 0);
		udelay(DB9_SATURN_DELAY);
		data[0] = db9_saturn_read_analog(port, type, powered);
		if (data[0] != 0x41) {
			/* read analog controller */
			for (i = 0; i < (data[0] & 0x0f); i++)
				data[i + 1] = db9_saturn_read_analog(port, type, powered);
			db9_saturn_write_sub(port, type, 3, powered, 0);
			return data[0];
		} else {
			/* read multitap */
			if (db9_saturn_read_analog(port, type, powered) != 0x60)
				return data[0] = 0xff;
			for (i = 0; i < 60; i += 10) {
				data[i] = db9_saturn_read_analog(port, type, powered);
				if (data[i] != 0xff)
					/* read each pad */
					for (j = 0; j < (data[i] & 0x0f); j++)
						data[i + j + 1] = db9_saturn_read_analog(port, type, powered);
			}
			db9_saturn_write_sub(port, type, 3, powered, 0);
			return 0x41;
		}
	case 0x0:
		/* 0000 : mouse */
		db9_saturn_write_sub(port, type, 2, powered, 0);
		udelay(DB9_SATURN_DELAY);
		tmp = db9_saturn_read_analog(port, type, powered);
		if (tmp == 0xff) {
			for (i = 0; i < 3; i++)
				data[i + 1] = db9_saturn_read_analog(port, type, powered);
			db9_saturn_write_sub(port, type, 3, powered, 0);
			return data[0] = 0xe3;
		}
	default:
		return data[0];
	}
}

/*
 * db9_saturn_report() analyzes packet and reports.
 */
static int db9_saturn_report(unsigned char id, unsigned char data[60], struct input_dev *devs[], int n, int max_pads)
{
	struct input_dev *dev;
	int tmp, i, j;

	tmp = (id == 0x41) ? 60 : 10;
	for (j = 0; j < tmp && n < max_pads; j += 10, n++) {
		dev = devs[n];
		switch (data[j]) {
		case 0x16: /* multi controller (analog 4 axis) */
			input_report_abs(dev, db9_abs[5], data[j + 6]);
		case 0x15: /* mission stick (analog 3 axis) */
			input_report_abs(dev, db9_abs[3], data[j + 4]);
			input_report_abs(dev, db9_abs[4], data[j + 5]);
		case 0x13: /* racing controller (analog 1 axis) */
			input_report_abs(dev, db9_abs[2], data[j + 3]);
		case 0x34: /* saturn keyboard (udlr ZXC ASD QE Esc) */
		case 0x02: /* digital pad (digital 2 axis + buttons) */
			input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
			input_report_abs(dev, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
			for (i = 0; i < 9; i++)
				input_report_key(dev, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
			break;
		case 0x19: /* mission stick x2 (analog 6 axis + buttons) */
			input_report_abs(dev, db9_abs[0], !(data[j + 1] & 128) - !(data[j + 1] & 64));
			input_report_abs(dev, db9_abs[1], !(data[j + 1] & 32) - !(data[j + 1] & 16));
			for (i = 0; i < 9; i++)
				input_report_key(dev, db9_cd32_btn[i], ~data[j + db9_saturn_byte[i]] & db9_saturn_mask[i]);
			input_report_abs(dev, db9_abs[2], data[j + 3]);
			input_report_abs(dev, db9_abs[3], data[j + 4]);
			input_report_abs(dev, db9_abs[4], data[j + 5]);
			/*
			input_report_abs(dev, db9_abs[8], (data[j + 6] & 128 ? 0 : 1) - (data[j + 6] & 64 ? 0 : 1));
			input_report_abs(dev, db9_abs[9], (data[j + 6] & 32 ? 0 : 1) - (data[j + 6] & 16 ? 0 : 1));
			*/
			input_report_abs(dev, db9_abs[6], data[j + 7]);
			input_report_abs(dev, db9_abs[7], data[j + 8]);
			input_report_abs(dev, db9_abs[5], data[j + 9]);
			break;
		case 0xd3: /* sankyo ff (analog 1 axis + stop btn) */
			input_report_key(dev, BTN_A, data[j + 3] & 0x80);
			input_report_abs(dev, db9_abs[2], data[j + 3] & 0x7f);
			break;
		case 0xe3: /* shuttle mouse (analog 2 axis + buttons. signed value) */
			input_report_key(dev, BTN_START, data[j + 1] & 0x08);
			input_report_key(dev, BTN_A, data[j + 1] & 0x04);
			input_report_key(dev, BTN_C, data[j + 1] & 0x02);
			input_report_key(dev, BTN_B, data[j + 1] & 0x01);
			input_report_abs(dev, db9_abs[2], data[j + 2] ^ 0x80);
			input_report_abs(dev, db9_abs[3], (0xff-(data[j + 3] ^ 0x80))+1); /* */
			break;
		case 0xff:
		default: /* no pad */
			input_report_abs(dev, db9_abs[0], 0);
			input_report_abs(dev, db9_abs[1], 0);
			for (i = 0; i < 9; i++)
				input_report_key(dev, db9_cd32_btn[i], 0);
			break;
		}
	}
	return n;
}

static int db9_saturn(int mode, struct parport *port, struct input_dev *devs[])
{
	unsigned char id, data[60];
	int type, n, max_pads;
	int tmp, i;

	switch (mode) {
	case DB9_SATURN_PAD:
		type = 0;
		n = 1;
		break;
	case DB9_SATURN_DPP:
		type = 1;
		n = 1;
		break;
	case DB9_SATURN_DPP_2:
		type = 1;
		n = 2;
		break;
	default:
		return -1;
	}
	max_pads = min(db9_modes[mode].n_pads, DB9_MAX_DEVICES);
	for (tmp = 0, i = 0; i < n; i++) {
		id = db9_saturn_read_packet(port, data, type + i, 1);
		tmp = db9_saturn_report(id, data, devs, tmp, max_pads);
	}
	return 0;
}

static void db9_timer(unsigned long private)
{
	struct db9 *db9 = (void *) private;
	struct parport *port = db9->pd->port;
	struct input_dev *dev = db9->dev[0];
	struct input_dev *dev2 = db9->dev[1];
	int data, i;

	switch (db9->mode) {
		case DB9_MULTI_0802_2:

			data = parport_read_data(port) >> 3;

			input_report_abs(dev2, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
			input_report_abs(dev2, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
			input_report_key(dev2, BTN_TRIGGER, ~data & DB9_FIRE1);

		case DB9_MULTI_0802:

			data = parport_read_status(port) >> 3;

			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
			input_report_key(dev, BTN_TRIGGER, data & DB9_FIRE1);
			break;

		case DB9_MULTI_STICK:

			data = parport_read_data(port);

			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
			input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
			break;

		case DB9_MULTI2_STICK:

			data = parport_read_data(port);

			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
			input_report_key(dev, BTN_TRIGGER, ~data & DB9_FIRE1);
			input_report_key(dev, BTN_THUMB,   ~data & DB9_FIRE2);
			break;

		case DB9_GENESIS_PAD:

			parport_write_control(port, DB9_NOSELECT);
			data = parport_read_data(port);

			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
			input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
			input_report_key(dev, BTN_C, ~data & DB9_FIRE2);

			parport_write_control(port, DB9_NORMAL);
			data = parport_read_data(port);

			input_report_key(dev, BTN_A,     ~data & DB9_FIRE1);
			input_report_key(dev, BTN_START, ~data & DB9_FIRE2);
			break;

		case DB9_GENESIS5_PAD:

			parport_write_control(port, DB9_NOSELECT);
			data = parport_read_data(port);

			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
			input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
			input_report_key(dev, BTN_C, ~data & DB9_FIRE2);

			parport_write_control(port, DB9_NORMAL);
			data = parport_read_data(port);

			input_report_key(dev, BTN_A,     ~data & DB9_FIRE1);
			input_report_key(dev, BTN_X,     ~data & DB9_FIRE2);
			input_report_key(dev, BTN_Y,     ~data & DB9_LEFT);
			input_report_key(dev, BTN_START, ~data & DB9_RIGHT);
			break;

		case DB9_GENESIS6_PAD:

			parport_write_control(port, DB9_NOSELECT); /* 1 */
			udelay(DB9_GENESIS6_DELAY);
			data = parport_read_data(port);

			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));
			input_report_key(dev, BTN_B, ~data & DB9_FIRE1);
			input_report_key(dev, BTN_C, ~data & DB9_FIRE2);

			parport_write_control(port, DB9_NORMAL);
			udelay(DB9_GENESIS6_DELAY);
			data = parport_read_data(port);

			input_report_key(dev, BTN_A, ~data & DB9_FIRE1);
			input_report_key(dev, BTN_START, ~data & DB9_FIRE2);

			parport_write_control(port, DB9_NOSELECT); /* 2 */
			udelay(DB9_GENESIS6_DELAY);
			parport_write_control(port, DB9_NORMAL);
			udelay(DB9_GENESIS6_DELAY);
			parport_write_control(port, DB9_NOSELECT); /* 3 */
			udelay(DB9_GENESIS6_DELAY);
			data=parport_read_data(port);

			input_report_key(dev, BTN_X,    ~data & DB9_LEFT);
			input_report_key(dev, BTN_Y,    ~data & DB9_DOWN);
			input_report_key(dev, BTN_Z,    ~data & DB9_UP);
			input_report_key(dev, BTN_MODE, ~data & DB9_RIGHT);

			parport_write_control(port, DB9_NORMAL);
			udelay(DB9_GENESIS6_DELAY);
			parport_write_control(port, DB9_NOSELECT); /* 4 */
			udelay(DB9_GENESIS6_DELAY);
			parport_write_control(port, DB9_NORMAL);
			break;

		case DB9_GENESIS6_DPADPRO:
			//added by ErV
			parport_write_data(port, 
			    DB9_GENESISDPADPRO_NOSELECT); /* 1 */
			udelay(DB9_GENESIS6_DELAY);
			data = parport_read_status(port);
			//data = parport_read_control(port); for up/down ?

			input_report_abs(dev, ABS_X, 
			    (data & DB9_GENESISDPADPRO_RIGHT ? 0 : 1) - 
			    (data & DB9_GENESISDPADPRO_LEFT ? 0 : 1));
			input_report_abs(dev, ABS_Y, 
			    (data & DB9_GENESISDPADPRO_DOWN  ? 0 : 1) - 
			    (data & DB9_GENESISDPADPRO_UP   ? 0 : 1));
			input_report_key(dev, BTN_B, 
			    ~data & DB9_GENESISDPADPRO_FIRE1);
			input_report_key(dev, BTN_C, 
			    ~data & DB9_GENESISDPADPRO_FIRE2);

			parport_write_data(port, DB9_GENESISDPADPRO_NORMAL);
			udelay(DB9_GENESIS6_DELAY);
			data = parport_read_status(port);

			input_report_key(dev, BTN_A, 
			    ~data & DB9_GENESISDPADPRO_FIRE1);
			input_report_key(dev, BTN_START, 
			    ~data & DB9_GENESISDPADPRO_FIRE2);

			parport_write_data(port, 
			    DB9_GENESISDPADPRO_NOSELECT); /* 2 */
			udelay(DB9_GENESIS6_DELAY);
			parport_write_data(port, 
			    DB9_GENESISDPADPRO_NORMAL);
			udelay(DB9_GENESIS6_DELAY);
			parport_write_data(port, 
			    DB9_GENESISDPADPRO_NOSELECT); /* 3 */
			udelay(DB9_GENESIS6_DELAY);
			data=parport_read_data(port);

			input_report_key(dev, BTN_X,    
			    ~data & DB9_GENESISDPADPRO_LEFT);
			input_report_key(dev, BTN_Y,    
			    ~data & DB9_GENESISDPADPRO_DOWN);
			input_report_key(dev, BTN_Z,    
			    ~data & DB9_GENESISDPADPRO_UP);
			input_report_key(dev, BTN_MODE, 
			    ~data & DB9_GENESISDPADPRO_RIGHT);

			parport_write_data(port, DB9_GENESISDPADPRO_NORMAL);
			udelay(DB9_GENESIS6_DELAY);
			parport_write_data(port, DB9_GENESISDPADPRO_NOSELECT); /* 4 */
			udelay(DB9_GENESIS6_DELAY);
			parport_write_data(port, DB9_GENESISDPADPRO_NORMAL);
			break;
			
		case DB9_SATURN_PAD:
		case DB9_SATURN_DPP:
		case DB9_SATURN_DPP_2:

			db9_saturn(db9->mode, port, db9->dev);
			break;

		case DB9_CD32_PAD:

			data = parport_read_data(port);

			input_report_abs(dev, ABS_X, (data & DB9_RIGHT ? 0 : 1) - (data & DB9_LEFT ? 0 : 1));
			input_report_abs(dev, ABS_Y, (data & DB9_DOWN  ? 0 : 1) - (data & DB9_UP   ? 0 : 1));

			parport_write_control(port, 0x0a);

			for (i = 0; i < 7; i++) {
				data = parport_read_data(port);
				parport_write_control(port, 0x02);
				parport_write_control(port, 0x0a);
				input_report_key(dev, db9_cd32_btn[i], ~data & DB9_FIRE2);
			}

			parport_write_control(port, 0x00);
			break;
		}

	input_sync(dev);

	mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
}

static int db9_open(struct input_dev *dev)
{
	struct db9 *db9 = dev->private;
	struct parport *port = db9->pd->port;
	int err;

	err = mutex_lock_interruptible(&db9->mutex);
	if (err)
		return err;

	if (!db9->used++) {
		parport_claim(db9->pd);
		parport_write_data(port, 0xff);
		if (db9_modes[db9->mode].reverse) {
			parport_data_reverse(port);
			parport_write_control(port, DB9_NORMAL);
		}
		mod_timer(&db9->timer, jiffies + DB9_REFRESH_TIME);
	}

	mutex_unlock(&db9->mutex);
	return 0;
}

static void db9_close(struct input_dev *dev)
{
	struct db9 *db9 = dev->private;
	struct parport *port = db9->pd->port;

	mutex_lock(&db9->mutex);
	if (!--db9->used) {
		del_timer_sync(&db9->timer);
		parport_write_control(port, 0x00);
		parport_data_forward(port);
		parport_release(db9->pd);
	}
	mutex_unlock(&db9->mutex);
}

static struct db9 __init *db9_probe(int parport, int mode)
{
	struct db9 *db9;
	const struct db9_mode_data *db9_mode;
	struct parport *pp;
	struct pardevice *pd;
	struct input_dev *input_dev;
	int i, j;
	int err;

	if (mode < 1 || mode >= DB9_MAX_PAD || !db9_modes[mode].n_buttons) {
		printk(KERN_ERR "db9.c: Bad device type %d\n", mode);
		err = -EINVAL;
		goto err_out;
	}

	db9_mode = &db9_modes[mode];

	pp = parport_find_number(parport);
	if (!pp) {
		printk(KERN_ERR "db9.c: no such parport\n");
		err = -ENODEV;
		goto err_out;
	}

	if (db9_mode->bidirectional && !(pp->modes & PARPORT_MODE_TRISTATE)) {
		printk(KERN_ERR "db9.c: specified parport is not bidirectional\n");
		err = -EINVAL;
		goto err_put_pp;
	}

	pd = parport_register_device(pp, "db9", NULL, NULL, NULL, PARPORT_DEV_EXCL, NULL);
	if (!pd) {
		printk(KERN_ERR "db9.c: parport busy already - lp.o loaded?\n");
		err = -EBUSY;
		goto err_put_pp;
	}

	db9 = kzalloc(sizeof(struct db9), GFP_KERNEL);
	if (!db9) {
		printk(KERN_ERR "db9.c: Not enough memory\n");
		err = -ENOMEM;
		goto err_unreg_pardev;
	}

	mutex_init(&db9->mutex);
	db9->pd = pd;
	db9->mode = mode;
	init_timer(&db9->timer);
	db9->timer.data = (long) db9;
	db9->timer.function = db9_timer;

	for (i = 0; i < (min(db9_mode->n_pads, DB9_MAX_DEVICES)); i++) {

		db9->dev[i] = input_dev = input_allocate_device();
		if (!input_dev) {
			printk(KERN_ERR "db9.c: Not enough memory for input device\n");
			err = -ENOMEM;
			goto err_unreg_devs;
		}

		snprintf(db9->phys[i], sizeof(db9->phys[i]),
			 "%s/input%d", db9->pd->port->name, i);

		input_dev->name = db9_mode->name;
		input_dev->phys = db9->phys[i];
		input_dev->id.bustype = BUS_PARPORT;
		input_dev->id.vendor = 0x0002;
		input_dev->id.product = mode;
		input_dev->id.version = 0x0100;
		input_dev->private = db9;

		input_dev->open = db9_open;
		input_dev->close = db9_close;

		input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
		for (j = 0; j < db9_mode->n_buttons; j++)
			set_bit(db9_mode->buttons[j], input_dev->keybit);
		for (j = 0; j < db9_mode->n_axis; j++) {
			if (j < 2)
				input_set_abs_params(input_dev, db9_abs[j], -1, 1, 0, 0);
			else
				input_set_abs_params(input_dev, db9_abs[j], 1, 255, 0, 0);
		}

		err = input_register_device(input_dev);
		if (err)
			goto err_free_dev;
	}

	parport_put_port(pp);
	return db9;

 err_free_dev:
	input_free_device(db9->dev[i]);
 err_unreg_devs:
	while (--i >= 0)
		input_unregister_device(db9->dev[i]);
	kfree(db9);
 err_unreg_pardev:
	parport_unregister_device(pd);
 err_put_pp:
	parport_put_port(pp);
 err_out:
	return ERR_PTR(err);
}

static void db9_remove(struct db9 *db9)
{
	int i;

	for (i = 0; i < min(db9_modes[db9->mode].n_pads, DB9_MAX_DEVICES); i++)
		input_unregister_device(db9->dev[i]);
	parport_unregister_device(db9->pd);
	kfree(db9);
}

static int __init db9_init(void)
{
	int i;
	int have_dev = 0;
	int err = 0;

	for (i = 0; i < DB9_MAX_PORTS; i++) {
		if (db9[i].nargs == 0 || db9[i].args[DB9_ARG_PARPORT] < 0)
			continue;

		if (db9[i].nargs < 2) {
			printk(KERN_ERR "db9.c: Device type must be specified.\n");
			err = -EINVAL;
			break;
		}

		db9_base[i] = db9_probe(db9[i].args[DB9_ARG_PARPORT],
					db9[i].args[DB9_ARG_MODE]);
		if (IS_ERR(db9_base[i])) {
			err = PTR_ERR(db9_base[i]);
			break;
		}

		have_dev = 1;
	}

	if (err) {
		while (--i >= 0)
			if (db9_base[i])
				db9_remove(db9_base[i]);
		return err;
	}

	return have_dev ? 0 : -ENODEV;
}

static void __exit db9_exit(void)
{
	int i;

	for (i = 0; i < DB9_MAX_PORTS; i++)
		if (db9_base[i])
			db9_remove(db9_base[i]);
}

module_init(db9_init);
module_exit(db9_exit);
Right now there is an error either in those constants:
Code:
#define DB9_DPADPRO_UP		0x01
...
or in code that checks buttons for joystick DB9_GENESIS6_DPADPRO
 
Old 01-04-2008, 02:58 PM   #13
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,202

Original Poster
Blog Entries: 3

Rep: Reputation: 62
I've changed following code in db9_timer
Code:
		case DB9_GENESIS6_DPADPRO:
			//added by ErV
			parport_write_data(port, 
			    DB9_GENESISDPADPRO_NOSELECT); /* 1 */
			udelay(DB9_GENESIS6_DELAY);
			data = parport_read_status(port);

			//data = parport_read_control(port); //for up/down ?
			//0x0F - unassigned, set
			//0x10 - C-button. unset if  pressed
			//0x20 - unassigned, set
			//0x40 - left, unset if pressed
			//0x80 - right, set if pressed
			//0xFF00 - zero
			input_report_abs(dev, ABS_X, 
			    (data & DB9_GENESISDPADPRO_RIGHT ? 1 : 0) - 
			    (data & DB9_GENESISDPADPRO_LEFT ? 0 : 1));
			input_report_key(dev, BTN_B, 
			    ~data & DB9_GENESISDPADPRO_FIRE1);
			input_report_key(dev, BTN_C, 
			    ~data & DB9_GENESISDPADPRO_FIRE2);
			//data = parport_read_control(port);
			//0x01 - 0
			//0x02 - 1
			//0x04 - 0
			//0x08 - 1
			//0x10 - 0 
			//0x20 - 0
			//0x40 - 0
			//0x80 - 0
			//0xF00
			
			input_report_abs(dev, ABS_Y, 
			    (data & DB9_GENESISPADPRO_DOWN  ? 1 : 0) - 
			    (data & DB9_GENESISDPADPRO_UP   ? 1 : 0));

			parport_write_data(port, DB9_GENESISDPADPRO_NORMAL);
			udelay(DB9_GENESIS6_DELAY);
			data = parport_read_status(port);

			input_report_key(dev, BTN_A, 
			    ~data & DB9_GENESISDPADPRO_FIRE1);
			input_report_key(dev, BTN_START, 
			    ~data & DB9_GENESISDPADPRO_FIRE2);

			parport_write_data(port, 
			    DB9_GENESISDPADPRO_NOSELECT); /* 2 */
			udelay(DB9_GENESIS6_DELAY);
			parport_write_data(port, 
			    DB9_GENESISDPADPRO_NORMAL);
			udelay(DB9_GENESIS6_DELAY);
			parport_write_data(port, 
			    DB9_GENESISDPADPRO_NOSELECT); /* 3 */
			udelay(DB9_GENESIS6_DELAY);
			data=parport_read_data(port);

			input_report_key(dev, BTN_X,    
			    ~data & DB9_GENESISDPADPRO_LEFT);
			input_report_key(dev, BTN_Y,    
			    ~data & DB9_GENESISDPADPRO_DOWN);
			input_report_key(dev, BTN_Z,    
			    ~data & DB9_GENESISDPADPRO_UP);
			input_report_key(dev, BTN_MODE, 
			    ~data & DB9_GENESISDPADPRO_RIGHT);

			parport_write_data(port, DB9_GENESISDPADPRO_NORMAL);
			udelay(DB9_GENESIS6_DELAY);
			parport_write_data(port, DB9_GENESISDPADPRO_NOSELECT); /* 4 */
			udelay(DB9_GENESIS6_DELAY);
			parport_write_data(port, DB9_GENESISDPADPRO_NORMAL);
			break;
and changed part of constant section (removed DB9_DAPDPRO_ constants):
Code:
#define DB9_GENESISDPADPRO_UP		PARPORT_CONTROL_STROBE
#define DB9_GENESISDPADPRO_DOWN		PARPORT_CONTROL_AUTOFD
#define DB9_GENESISDPADPRO_LEFT		PARPORT_STATUS_ACK
#define DB9_GENESISDPADPRO_RIGHT	PARPORT_STATUS_BUSY
#define DB9_GENESISDPADPRO_FIRE1	PARPORT_STATUS_PAPEROUT
#define DB9_GENESISDPADPRO_FIRE2	PARPORT_STATUS_SELECT
#define DB9_GENESISDPADPRO_FIRE3	0x40
#define DB9_GENESISDPADPRO_FIRE4	0x80

#define DB9_GENESISDPADPRO_NORMAL	0xFF
#define DB9_GENESISDPADPRO_NOSELECT	0xFE
The situation is following:
joystick correctly reacts to pressing "left" and "right", it also reacts to "b" and "c" buttons. However, it ignores anything else, and pressing "b" also presses "a", while pressing "c" also presses "y". (I'm using KDE control center "peripherals->joystick" section to check it).

Also, I either don't know how to read data from Autofeed and Strobe buttons, or joystick is fried.
Reading/writing to data pins is very straighforward - it is done through parport_read_data or parport_write_data, however reading using parport_read_status gives number that doesn't change (see comments in the piece of code abouve). So it looks like either joystick is dead, or I'm doing something wrong way.

I'll check joystick, and write write back after that.
 
Old 01-04-2008, 05:10 PM   #14
ErV
Senior Member
 
Registered: Mar 2007
Location: Russia
Distribution: Slackware 12.2
Posts: 1,202

Original Poster
Blog Entries: 3

Rep: Reputation: 62
Well, the question is answered.

It looks liks it isn't possible to connect Sega Genesis joystick with DirectPadPro interface using current version of "parporot" kernel module and by hacking db9.c. At least, I don't know about such way.

Reason:
db9.ko uses parport.ko to access parallel port.

For parport.ko, there are three kind of pins:
data (data0-data8), status(error, select, paperout, ack, busy) , and control(strobe, autofeed, init, select).
"status" pins are read-only, "control" and "data" pins are read/write (using functions like parport_read_data, parport_write_data, etc.), but there is a little trouble:
what "parport_read_control" returns is really last written value (at least, documentation says so). I.e. I can't read control pins using parport module, although it might be possible with real hardware and maybe another kernel parport module I don't know about. (Also, It looks like some more specialized modules allow to read control pins state, but I'm not sure if this is what I need -i.e. this might be actually last-written value :-\)

Unfortunately, DirectPadPro interface uses strobe and autofeed control lines to receive state of Up and Down buttons, which are also used as "X" and "Z". So it won't work.

As for button "A" being pressed together with "B" and "Y"(it was a misprint before, pressing "С" also presses "start", not "Y") being pressed together with "C", it looks like there is some programming bug (my own, of course) and state of the status pins isn't being reread after sending control pulses to joystick.

So, to make it short.
Even if I'll fix "sticky buttons" bug, it won't be possible to use Up, Down, X and Z buttons - the just won't work. This is because I don't know how to read the state of Autofeed (signal that joystick sends to that pin, I don't need last-written value) and Strobe pins. If there is a way to do this, then it's possible to use DPadPro interface.
Also there might be another module for parallel port, that supports reading from those control pins. although in this case I'll have to write a full driver for joystick and won't be able to hack existing db9.ko.

So I suppose it's better to rebuild the DirectPadPro interface into Linux interface, or it is possible to make custom interface (that doesn't send signals to unusual pins) and create a custom version of db9.ko for it (this is easy. Well, relatively easy).
Also, it might be possible to change behaviour of parport, but it looks like it is a kind of wrapper around of bunch of other specialized parport drivers (although I'm not really sure about that), so I think messing with this behaviour isn't good idea.

I believe that's all. So, next time I'll need Sega MegaDrive joystick, I'll rebuild interface with soldering iron.

2archtoad6
Thanks for writing that last comment. If I didn't receive notification about it, I'd probably never looked into this problem after all (It's just too much happened during that time and I've almost forgot about that joystick driver). Hacking kernel driver and digging parport information was quite interesting, even if it didn't solve problem.

Last edited by ErV; 01-04-2008 at 05:37 PM.
 
  


Reply

Tags
art, ascii, asciiart


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Sega Genesis Emulator doralsoral Linux - Games 1 06-06-2007 01:54 PM
linux rs-232 button interface pandersson61 Linux - Hardware 3 10-13-2006 08:55 PM
2 button joystick wont work jostick help Linux - Hardware 1 07-05-2005 09:32 AM
Stange joystick problem (Sidewinder precision pro) Ut2004 tackettb Fedora 0 08-21-2004 12:16 PM
Genesis Emaulation joystick woes GT_Onizuka Linux - Games 0 07-15-2004 11:49 AM

LinuxQuestions.org > Forums > Linux Forums > Linux - Hardware

All times are GMT -5. The time now is 04:55 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration