Commit 90324bfd authored by Peter Nelson's avatar Peter Nelson Committed by Vojtech Pavlik

input: For now, a bug in the PSX controllers support in gamecon prevents

hot-swapping of such controllers. If a controllers is removed then all
the controllers stop working and cpu usage gets high. The attached patch
(against 2.6.11-rc3) corrects this bug by checking the information read
from the controller. If the message length is bigger than the maximum
possible, then it means the controller is not there and therefore this
value should be discarded.

Note that this is a re-send of a previous patch now that the patch of
Peter (which had to be applied before this one) has been intregrated in
the vanilla kernel. It's Peter's version modified to apply cleanly
against 2.6.11-rc3 plus a fix in the comment.
Signed-off-by: default avatarPeter Nelson <rufus-kernel@hackish.org>
Signed-off-by: default avatarEric Piel <eric.piel@tremplin-utc.net>
parent 6a6bfca1
......@@ -227,7 +227,8 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
*/
#define GC_PSX_DELAY 25 /* 25 usec */
#define GC_PSX_LENGTH 8 /* talk to the controller in bytes */
#define GC_PSX_LENGTH 8 /* talk to the controller in bits */
#define GC_PSX_BYTES 6 /* the maximum number of bytes to read off the controller */
#define GC_PSX_MOUSE 1 /* Mouse */
#define GC_PSX_NEGCON 2 /* NegCon */
......@@ -241,7 +242,7 @@ static void gc_multi_read_packet(struct gc *gc, int length, unsigned char *data)
#define GC_PSX_SELECT 0x02 /* Pin 3 */
#define GC_PSX_ID(x) ((x) >> 4) /* High nibble is device type */
#define GC_PSX_LEN(x) ((x) & 0xf) /* Low nibble is length in words */
#define GC_PSX_LEN(x) (((x) & 0xf) << 1) /* Low nibble is length in bytes/2 */
static int gc_psx_delay = GC_PSX_DELAY;
module_param_named(psx_delay, gc_psx_delay, uint, 0);
......@@ -259,13 +260,13 @@ static short gc_psx_ddr_btn[] = { BTN_0, BTN_1, BTN_2, BTN_3 };
* the psx pad.
*/
static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_PSX_LENGTH])
static void gc_psx_command(struct gc *gc, int b, unsigned char data[5])
{
int i, j, cmd, read;
for (i = 0; i < 5; i++)
data[i] = 0;
for (i = 0; i < 8; i++, b >>= 1) {
for (i = 0; i < GC_PSX_LENGTH; i++, b >>= 1) {
cmd = (b & 1) ? GC_PSX_COMMAND : 0;
parport_write_data(gc->pd->port, cmd | GC_PSX_POWER);
udelay(gc_psx_delay);
......@@ -282,7 +283,7 @@ static void gc_psx_command(struct gc *gc, int b, unsigned char data[GC_PSX_LENGT
* device identifier code.
*/
static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_LENGTH], unsigned char id[5])
static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_BYTES], unsigned char id[5])
{
int i, j, max_len = 0;
unsigned long flags;
......@@ -300,10 +301,12 @@ static void gc_psx_read_packet(struct gc *gc, unsigned char data[5][GC_PSX_LENGT
gc_psx_command(gc, 0, data2); /* Dump status */
for (i =0; i < 5; i++) /* Find the longest pad */
if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR])) && (GC_PSX_LEN(id[i]) > max_len))
if((gc_status_bit[i] & (gc->pads[GC_PSX] | gc->pads[GC_DDR]))
&& (GC_PSX_LEN(id[i]) > max_len)
&& (GC_PSX_LEN(id[i]) <= GC_PSX_BYTES))
max_len = GC_PSX_LEN(id[i]);
for (i = 0; i < max_len * 2; i++) { /* Read in all the data */
for (i = 0; i < max_len; i++) { /* Read in all the data */
gc_psx_command(gc, 0, data2);
for (j = 0; j < 5; j++)
data[j][i] = data2[j];
......@@ -328,7 +331,7 @@ static void gc_timer(unsigned long private)
struct gc *gc = (void *) private;
struct input_dev *dev = gc->dev;
unsigned char data[GC_MAX_LENGTH];
unsigned char data_psx[5][GC_PSX_LENGTH];
unsigned char data_psx[5][GC_PSX_BYTES];
int i, j, s;
/*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment