cregit-Linux how code gets into the kernel

Release 4.14 drivers/input/joystick/cobra.c

/*
 *  Copyright (c) 1999-2001 Vojtech Pavlik
 */

/*
 * Creative Labs Blaster GamePad Cobra driver for Linux
 */

/*
 * 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 <vojtech@ucw.cz>, or by paper mail:
 * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/input.h>
#include <linux/jiffies.h>


#define DRIVER_DESC	"Creative Labs Blaster GamePad Cobra driver"

MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");

MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");


#define COBRA_MAX_STROBE	45	
/* 45 us max wait for first strobe */

#define COBRA_LENGTH		36


static int cobra_btn[] = { BTN_START, BTN_SELECT, BTN_TL, BTN_TR, BTN_X, BTN_Y, BTN_Z, BTN_A, BTN_B, BTN_C, BTN_TL2, BTN_TR2, 0 };


struct cobra {
	
struct gameport *gameport;
	
struct input_dev *dev[2];
	
int reads;
	
int bads;
	
unsigned char exists;
	
char phys[2][32];
};


static unsigned char cobra_read_packet(struct gameport *gameport, unsigned int *data) { unsigned long flags; unsigned char u, v, w; __u64 buf[2]; int r[2], t[2]; int i, j, ret; int strobe = gameport_time(gameport, COBRA_MAX_STROBE); for (i = 0; i < 2; i++) { r[i] = buf[i] = 0; t[i] = COBRA_MAX_STROBE; } local_irq_save(flags); u = gameport_read(gameport); do { t[0]--; t[1]--; v = gameport_read(gameport); for (i = 0, w = u ^ v; i < 2 && w; i++, w >>= 2) if (w & 0x30) { if ((w & 0x30) < 0x30 && r[i] < COBRA_LENGTH && t[i] > 0) { buf[i] |= (__u64)((w >> 5) & 1) << r[i]++; t[i] = strobe; u = v; } else t[i] = 0; } } while (t[0] > 0 || t[1] > 0); local_irq_restore(flags); ret = 0; for (i = 0; i < 2; i++) { if (r[i] != COBRA_LENGTH) continue; for (j = 0; j < COBRA_LENGTH && (buf[i] & 0x04104107f) ^ 0x041041040; j++) buf[i] = (buf[i] >> 1) | ((__u64)(buf[i] & 1) << (COBRA_LENGTH - 1)); if (j < COBRA_LENGTH) ret |= (1 << i); data[i] = ((buf[i] >> 7) & 0x000001f) | ((buf[i] >> 8) & 0x00003e0) | ((buf[i] >> 9) & 0x0007c00) | ((buf[i] >> 10) & 0x00f8000) | ((buf[i] >> 11) & 0x1f00000); } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)42799.53%250.00%
Ingo Molnar20.47%250.00%
Total429100.00%4100.00%


static void cobra_poll(struct gameport *gameport) { struct cobra *cobra = gameport_get_drvdata(gameport); struct input_dev *dev; unsigned int data[2]; int i, j, r; cobra->reads++; if ((r = cobra_read_packet(gameport, data)) != cobra->exists) { cobra->bads++; return; } for (i = 0; i < 2; i++) if (cobra->exists & r & (1 << i)) { dev = cobra->dev[i]; input_report_abs(dev, ABS_X, ((data[i] >> 4) & 1) - ((data[i] >> 3) & 1)); input_report_abs(dev, ABS_Y, ((data[i] >> 2) & 1) - ((data[i] >> 1) & 1)); for (j = 0; cobra_btn[j]; j++) input_report_key(dev, cobra_btn[j], data[i] & (0x20 << j)); input_sync(dev); } }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)19490.65%233.33%
Dmitry Torokhov146.54%233.33%
Vojtech Pavlik52.34%116.67%
Linus Torvalds10.47%116.67%
Total214100.00%6100.00%


static int cobra_open(struct input_dev *dev) { struct cobra *cobra = input_get_drvdata(dev); gameport_start_polling(cobra->gameport); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2683.87%250.00%
Dmitry Torokhov516.13%250.00%
Total31100.00%4100.00%


static void cobra_close(struct input_dev *dev) { struct cobra *cobra = input_get_drvdata(dev); gameport_stop_polling(cobra->gameport); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)2382.14%250.00%
Dmitry Torokhov517.86%250.00%
Total28100.00%4100.00%


static int cobra_connect(struct gameport *gameport, struct gameport_driver *drv) { struct cobra *cobra; struct input_dev *input_dev; unsigned int data[2]; int i, j; int err; cobra = kzalloc(sizeof(struct cobra), GFP_KERNEL); if (!cobra) return -ENOMEM; cobra->gameport = gameport; gameport_set_drvdata(gameport, cobra); err = gameport_open(gameport, drv, GAMEPORT_MODE_RAW); if (err) goto fail1; cobra->exists = cobra_read_packet(gameport, data); for (i = 0; i < 2; i++) if ((cobra->exists >> i) & data[i] & 1) { printk(KERN_WARNING "cobra.c: Device %d on %s has the Ext bit set. ID is: %d" " Contact vojtech@ucw.cz\n", i, gameport->phys, (data[i] >> 2) & 7); cobra->exists &= ~(1 << i); } if (!cobra->exists) { err = -ENODEV; goto fail2; } gameport_set_poll_handler(gameport, cobra_poll); gameport_set_poll_interval(gameport, 20); for (i = 0; i < 2; i++) { if (~(cobra->exists >> i) & 1) continue; cobra->dev[i] = input_dev = input_allocate_device(); if (!input_dev) { err = -ENOMEM; goto fail3; } snprintf(cobra->phys[i], sizeof(cobra->phys[i]), "%s/input%d", gameport->phys, i); input_dev->name = "Creative Labs Blaster GamePad Cobra"; input_dev->phys = cobra->phys[i]; input_dev->id.bustype = BUS_GAMEPORT; input_dev->id.vendor = GAMEPORT_ID_VENDOR_CREATIVE; input_dev->id.product = 0x0008; input_dev->id.version = 0x0100; input_dev->dev.parent = &gameport->dev; input_set_drvdata(input_dev, cobra); input_dev->open = cobra_open; input_dev->close = cobra_close; input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_set_abs_params(input_dev, ABS_X, -1, 1, 0, 0); input_set_abs_params(input_dev, ABS_Y, -1, 1, 0, 0); for (j = 0; cobra_btn[j]; j++) set_bit(cobra_btn[j], input_dev->keybit); err = input_register_device(cobra->dev[i]); if (err) goto fail4; } return 0; fail4: input_free_device(cobra->dev[i]); fail3: while (--i >= 0) if (cobra->dev[i]) input_unregister_device(cobra->dev[i]); fail2: gameport_close(gameport); fail1: gameport_set_drvdata(gameport, NULL); kfree(cobra); return err; }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)25648.58%213.33%
Dmitry Torokhov22442.50%960.00%
Vojtech Pavlik448.35%213.33%
Jiri Slaby20.38%16.67%
Pekka J Enberg10.19%16.67%
Total527100.00%15100.00%


static void cobra_disconnect(struct gameport *gameport) { struct cobra *cobra = gameport_get_drvdata(gameport); int i; for (i = 0; i < 2; i++) if ((cobra->exists >> i) & 1) input_unregister_device(cobra->dev[i]); gameport_close(gameport); gameport_set_drvdata(gameport, NULL); kfree(cobra); }

Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)6180.26%250.00%
Dmitry Torokhov1519.74%250.00%
Total76100.00%4100.00%

static struct gameport_driver cobra_drv = { .driver = { .name = "cobra", }, .description = DRIVER_DESC, .connect = cobra_connect, .disconnect = cobra_disconnect, }; module_gameport_driver(cobra_drv);

Overall Contributors

PersonTokensPropCommitsCommitProp
Linus Torvalds (pre-git)108474.20%28.33%
Dmitry Torokhov28619.58%937.50%
Vojtech Pavlik785.34%416.67%
Tim Schmielau30.21%14.17%
Ingo Molnar20.14%28.33%
Jiri Slaby20.14%14.17%
Axel Lin20.14%14.17%
Linus Torvalds20.14%28.33%
Adrian Bunk10.07%14.17%
Pekka J Enberg10.07%14.17%
Total1461100.00%24100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.