📄 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){ struct grip_port *port; u32 packet; int joytype = 0; int slot; /* 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; port = grip->port[slot]; /* * 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 (port->registered) { printk(KERN_INFO "grip_mp: removing %s, slot %d\n", grip_name[port->mode], slot); input_unregister_device(port->dev); port->registered = 0; } dbg("Reset: grip multiport slot %d\n", slot); port->mode = 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 */ port->buttons = (~packet) & 0xff; port->yaxes = ((axis_map[dir] >> 2) & 3) - 1; port->xaxes = (axis_map[dir] & 3) - 1; port->dirty = 1; if (port->mode == GRIP_MODE_RESET) flags |= IO_SLOT_CHANGE; port->mode = GRIP_MODE_GP; if (!port->registered) { 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->port[slot]->mode == GRIP_MODE_RESET) invalid = 1; if (grip->port[slot]->mode != 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 activated.\n"); else { dbg("multiport_init(): unable to activate 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 grip_port *port = grip->port[slot]; int i; /* Store button states with linux input driver */ for (i = 0; i < 8; i++) input_report_key(port->dev, grip_btn_gp[i], (port->buttons >> i) & 1); /* Store axis states with linux driver */ input_report_abs(port->dev, ABS_X, port->xaxes); input_report_abs(port->dev, ABS_Y, port->yaxes); /* Tell the receiver of the events to process them */ input_sync(port->dev); port->dirty = 0;}/* * Get the multiport state. */static void grip_poll(struct gameport *gameport){ struct grip_mp *grip = gameport_get_drvdata(gameport); 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->port[i]->dirty) 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; gameport_start_polling(grip->gameport); return 0;}/* * Called when a joystick device file is closed */static void grip_close(struct input_dev *dev){ struct grip_mp *grip = dev->private; gameport_start_polling(grip->gameport);}/* * Tell the linux input layer about a newly plugged-in gamepad. */static int register_slot(int slot, struct grip_mp *grip){ struct grip_port *port = grip->port[slot]; struct input_dev *input_dev; int j, t; port->dev = input_dev = input_allocate_device(); if (!input_dev) return -ENOMEM; input_dev->name = grip_name[port->mode]; input_dev->id.bustype = BUS_GAMEPORT; input_dev->id.vendor = GAMEPORT_ID_VENDOR_GRAVIS; input_dev->id.product = 0x0100 + port->mode; input_dev->id.version = 0x0100; input_dev->cdev.dev = &grip->gameport->dev; input_dev->private = grip; input_dev->open = grip_open; input_dev->close = grip_close; input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); for (j = 0; (t = grip_abs[port->mode][j]) >= 0; j++) input_set_abs_params(input_dev, t, -1, 1, 0, 0); for (j = 0; (t = grip_btn[port->mode][j]) >= 0; j++) if (t > 0) set_bit(t, input_dev->keybit); input_register_device(port->dev); port->registered = 1; if (port->dirty) /* report initial state, if any */ report_slot(grip, slot); return 0;}static int grip_connect(struct gameport *gameport, struct gameport_driver *drv){ struct grip_mp *grip; int err; if (!(grip = kzalloc(sizeof(struct grip_mp), GFP_KERNEL))) return -ENOMEM; grip->gameport = gameport; gameport_set_drvdata(gameport, grip); err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW); if (err) goto fail1; gameport_set_poll_handler(gameport, grip_poll); gameport_set_poll_interval(gameport, 20); if (!multiport_init(grip)) { err = -ENODEV; goto fail2; } if (!grip->port[0]->mode && !grip->port[1]->mode && !grip->port[2]->mode && !grip->port[3]->mode) { /* nothing plugged in */ err = -ENODEV; goto fail2; } return 0;fail2: gameport_close(gameport);fail1: gameport_set_drvdata(gameport, NULL); kfree(grip); return err;}static void grip_disconnect(struct gameport *gameport){ struct grip_mp *grip = gameport_get_drvdata(gameport); int i; for (i = 0; i < 4; i++) if (grip->port[i]->registered) input_unregister_device(grip->port[i]->dev); gameport_close(gameport); gameport_set_drvdata(gameport, NULL); kfree(grip);}static struct gameport_driver grip_drv = { .driver = { .name = "grip_mp", }, .description = DRIVER_DESC, .connect = grip_connect, .disconnect = grip_disconnect,};static int __init grip_init(void){ gameport_register_driver(&grip_drv); return 0;}static void __exit grip_exit(void){ gameport_unregister_driver(&grip_drv);}module_init(grip_init);module_exit(grip_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -