📄 grip_mp.c
字号:
else bads++; } return 0;}/* * Packet structure: B0-B15 => gamepad state * B16-B20 => gamepad device type * B21-B24 => multiport slot index (1-4) * * Known device types: 0x1f (grip pad), 0x0 (no device). Others may exist. * * Returns the packet status. */static int get_and_decode_packet(struct grip_mp *grip, int flags){ u32 packet; int joytype = 0; int slot = 0; /* Get a packet and check for validity */ flags &= IO_RESET | IO_RETRY; flags = multiport_io(grip->gameport, flags, 0, &packet); grip->reads++; if (packet & PACKET_MP_DONE) flags |= IO_DONE; if (flags && !(flags & IO_GOT_PACKET)) { grip->bads++; return flags; } /* Ignore non-gamepad packets, e.g. multiport hardware version */ slot = ((packet >> 21) & 0xf) - 1; if ((slot < 0) || (slot > 3)) return flags; /* * Handle "reset" packets, which occur at startup, and when gamepads * are removed or plugged in. May contain configuration of a new gamepad. */ joytype = (packet >> 16) & 0x1f; if (!joytype) { if (grip->registered[slot]) { printk(KERN_INFO "grip_mp: removing %s, slot %d\n", grip_name[grip->mode[slot]], slot); input_unregister_device(grip->dev + slot); grip->registered[slot] = 0; } dbg("Reset: grip multiport slot %d\n", slot); grip->mode[slot] = GRIP_MODE_RESET; flags |= IO_SLOT_CHANGE; return flags; } /* Interpret a grip pad packet */ if (joytype == 0x1f) { int dir = (packet >> 8) & 0xf; /* eight way directional value */ grip->buttons[slot] = (~packet) & 0xff; grip->yaxes[slot] = ((axis_map[dir] >> 2) & 3) - 1; grip->xaxes[slot] = (axis_map[dir] & 3) - 1; grip->dirty[slot] = 1; if (grip->mode[slot] == GRIP_MODE_RESET) flags |= IO_SLOT_CHANGE; grip->mode[slot] = GRIP_MODE_GP; if (!grip->registered[slot]) { dbg("New Grip pad in multiport slot %d.\n", slot); register_slot(slot, grip); } return flags; } /* Handle non-grip device codes. For now, just print diagnostics. */ { static int strange_code = 0; if (strange_code != joytype) { printk(KERN_INFO "Possible non-grip pad/joystick detected.\n"); printk(KERN_INFO "Got joy type 0x%x and packet 0x%x.\n", joytype, packet); strange_code = joytype; } } return flags;}/* * Returns true if all multiport slot states appear valid. */static int slots_valid(struct grip_mp *grip){ int flags, slot, invalid = 0, active = 0; flags = get_and_decode_packet(grip, 0); if (!(flags & IO_GOT_PACKET)) return 0; for (slot = 0; slot < 4; slot++) { if (grip->mode[slot] == GRIP_MODE_RESET) invalid = 1; if (grip->mode[slot] != GRIP_MODE_NONE) active = 1; } /* Return true if no active slot but multiport sent all its data */ if (!active) return (flags & IO_DONE) ? 1 : 0; /* Return false if invalid device code received */ return invalid ? 0 : 1;}/* * Returns whether the multiport was placed into digital mode and * able to communicate its state successfully. */static int multiport_init(struct grip_mp *grip){ int dig_mode, initialized = 0, tries = 0; u32 packet; dig_mode = dig_mode_start(grip->gameport, &packet); while (!dig_mode && tries < 4) { dig_mode = dig_mode_start(grip->gameport, &packet); tries++; } if (dig_mode) dbg("multiport_init(): digital mode achieved.\n"); else { dbg("multiport_init(): unable to achieve digital mode.\n"); return 0; } /* Get packets, store multiport state, and check state's validity */ for (tries = 0; tries < 4096; tries++) { if ( slots_valid(grip) ) { initialized = 1; break; } } dbg("multiport_init(): initialized == %d\n", initialized); return initialized;}/* * Reports joystick state to the linux input layer. */static void report_slot(struct grip_mp *grip, int slot){ struct input_dev *dev = &(grip->dev[slot]); int i, buttons = grip->buttons[slot]; /* Store button states with linux input driver */ for (i = 0; i < 8; i++) input_report_key(dev, grip_btn_gp[i], (buttons >> i) & 1); /* Store axis states with linux driver */ input_report_abs(dev, ABS_X, grip->xaxes[slot]); input_report_abs(dev, ABS_Y, grip->yaxes[slot]); /* Tell the receiver of the events to process them */ input_sync(dev); grip->dirty[slot] = 0;}/* * Get the multiport state. */static void get_and_report_mp_state(struct grip_mp *grip){ int i, npkts, flags; for (npkts = 0; npkts < 4; npkts++) { flags = IO_RETRY; for (i = 0; i < 32; i++) { flags = get_and_decode_packet(grip, flags); if ((flags & IO_GOT_PACKET) || !(flags & IO_RETRY)) break; } if (flags & IO_DONE) break; } for (i = 0; i < 4; i++) if (grip->dirty[i]) report_slot(grip, i);}/* * Called when a joystick device file is opened */static int grip_open(struct input_dev *dev){ struct grip_mp *grip = dev->private; if (!grip->used++) mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME); return 0;}/* * Called when a joystick device file is closed */static void grip_close(struct input_dev *dev){ struct grip_mp *grip = dev->private; if (!--grip->used) del_timer(&grip->timer);}/* * Tell the linux input layer about a newly plugged-in gamepad. */static void register_slot(int slot, struct grip_mp *grip){ int j, t; grip->dev[slot].private = grip; grip->dev[slot].open = grip_open; grip->dev[slot].close = grip_close; grip->dev[slot].name = grip_name[grip->mode[slot]]; grip->dev[slot].id.bustype = BUS_GAMEPORT; grip->dev[slot].id.vendor = GAMEPORT_ID_VENDOR_GRAVIS; grip->dev[slot].id.product = 0x0100 + grip->mode[slot]; grip->dev[slot].id.version = 0x0100; grip->dev[slot].evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (j = 0; (t = grip_abs[grip->mode[slot]][j]) >= 0; j++) { set_bit(t, grip->dev[slot].absbit); grip->dev[slot].absmin[t] = -1; grip->dev[slot].absmax[t] = 1; } for (j = 0; (t = grip_btn[grip->mode[slot]][j]) >= 0; j++) if (t > 0) set_bit(t, grip->dev[slot].keybit); input_register_device(grip->dev + slot); grip->registered[slot] = 1; if (grip->dirty[slot]) /* report initial state, if any */ report_slot(grip, slot); printk(KERN_INFO "grip_mp: added %s, slot %d\n", grip_name[grip->mode[slot]], slot);}/* * Repeatedly polls the multiport and generates events. */static void grip_timer(unsigned long private){ struct grip_mp *grip = (void*) private; get_and_report_mp_state(grip); mod_timer(&grip->timer, jiffies + GRIP_REFRESH_TIME);}static void grip_connect(struct gameport *gameport, struct gameport_dev *dev){ struct grip_mp *grip; if (!(grip = kmalloc(sizeof(struct grip_mp), GFP_KERNEL))) return; memset(grip, 0, sizeof(struct grip_mp)); gameport->private = grip; grip->gameport = gameport; init_timer(&grip->timer); grip->timer.data = (long) grip; grip->timer.function = grip_timer; if (gameport_open(gameport, dev, GAMEPORT_MODE_RAW)) goto fail1; if (!multiport_init(grip)) goto fail2; if (!grip->mode[0] && !grip->mode[1] && /* nothing plugged in */ !grip->mode[2] && !grip->mode[3]) goto fail2; return;fail2: gameport_close(gameport);fail1: kfree(grip);}static void grip_disconnect(struct gameport *gameport){ int i; struct grip_mp *grip = gameport->private; for (i = 0; i < 4; i++) if (grip->registered[i]) input_unregister_device(grip->dev + i); gameport_close(gameport); kfree(grip);}static struct gameport_dev grip_dev = { .connect = grip_connect, .disconnect = grip_disconnect,};static int grip_init(void){ gameport_register_device(&grip_dev); return 0;}static void grip_exit(void){ gameport_unregister_device(&grip_dev);}module_init(grip_init);module_exit(grip_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -