You can subscribe to this list here.
| 2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(135) |
Nov
(123) |
Dec
(83) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2002 |
Jan
(244) |
Feb
(72) |
Mar
(221) |
Apr
(91) |
May
(104) |
Jun
(93) |
Jul
(78) |
Aug
(1) |
Sep
(1) |
Oct
(29) |
Nov
(98) |
Dec
(20) |
| 2003 |
Jan
|
Feb
(21) |
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
(18) |
Sep
(18) |
Oct
(23) |
Nov
(12) |
Dec
(6) |
| 2004 |
Jan
(2) |
Feb
(32) |
Mar
|
Apr
(12) |
May
(11) |
Jun
(11) |
Jul
|
Aug
(9) |
Sep
|
Oct
(15) |
Nov
|
Dec
|
| 2005 |
Jan
|
Feb
(2) |
Mar
(11) |
Apr
(6) |
May
(1) |
Jun
(9) |
Jul
(7) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
| 2006 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2007 |
Jan
|
Feb
(2) |
Mar
|
Apr
(25) |
May
(2) |
Jun
|
Jul
(5) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2008 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2009 |
Jan
|
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2010 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(13) |
Oct
|
Nov
(2) |
Dec
(2) |
| 2011 |
Jan
|
Feb
|
Mar
(10) |
Apr
(10) |
May
(1) |
Jun
(6) |
Jul
|
Aug
(2) |
Sep
(5) |
Oct
|
Nov
|
Dec
|
|
From: James S. <jsi...@us...> - 2002-01-23 05:00:49
|
Update of /cvsroot/linuxconsole/ruby In directory usw-pr-cvs1:/tmp/cvs-serv32404 Removed Files: AGAINST-2.5.1 Log Message: --- AGAINST-2.5.1 DELETED --- |
|
From: James S. <jsi...@us...> - 2002-01-23 04:58:42
|
Update of /cvsroot/linuxconsole/ruby In directory usw-pr-cvs1:/tmp/cvs-serv31862 Added Files: AGAINST-2.5.2 Log Message: --- NEW FILE: AGAINST-2.5.2 --- |
|
From: James S. <jsi...@us...> - 2002-01-23 00:17:11
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/char
In directory usw-pr-cvs1:/tmp/cvs-serv4459
Modified Files:
keyboard.c
Log Message:
Forgot to remove absolete wait_keypress function.
Index: keyboard.c
===================================================================
RCS file: /cvsroot/linuxconsole/ruby/linux/drivers/char/keyboard.c,v
retrieving revision 1.65
retrieving revision 1.66
diff -u -d -r1.65 -r1.66
--- keyboard.c 2002/01/08 18:45:03 1.65
+++ keyboard.c 2002/01/23 00:17:08 1.66
@@ -123,15 +123,7 @@
/*
* Variables/function exported for vt.c
*/
-
int shift_state = 0;
-DECLARE_WAIT_QUEUE_HEAD(keypress_wait);
-
-int keyboard_wait_for_keypress(struct console *console)
-{
- sleep_on(&keypress_wait);
- return 0;
-}
/*
* Internal data.
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 21:12:05
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/serio
In directory usw-pr-cvs1:/tmp/cvs-serv21451
Modified Files:
Tag: 1.15
serio.c
Log Message:
Moved.
--- NEW FILE: serio.c ---
/*
* $Id: serio.c,v 1.15 2002/01/22 21:12:03 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* The Serio abstraction module
*/
/*
* 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/serio.h>
#include <linux/errno.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>");
MODULE_DESCRIPTION("Serio abstraction core");
MODULE_LICENSE("GPL");
EXPORT_SYMBOL(serio_register_port);
EXPORT_SYMBOL(serio_unregister_port);
EXPORT_SYMBOL(serio_register_device);
EXPORT_SYMBOL(serio_unregister_device);
EXPORT_SYMBOL(serio_open);
EXPORT_SYMBOL(serio_close);
EXPORT_SYMBOL(serio_rescan);
static struct serio *serio_list;
static struct serio_dev *serio_dev;
static void serio_find_dev(struct serio *serio)
{
struct serio_dev *dev = serio_dev;
while (dev && !serio->dev) {
if (dev->connect)
dev->connect(serio, dev);
dev = dev->next;
}
}
void serio_rescan(struct serio *serio)
{
if (serio->dev && serio->dev->disconnect)
serio->dev->disconnect(serio);
serio_find_dev(serio);
}
void serio_register_port(struct serio *serio)
{
serio->next = serio_list;
serio_list = serio;
serio_find_dev(serio);
}
void serio_unregister_port(struct serio *serio)
{
struct serio **serioptr = &serio_list;
while (*serioptr && (*serioptr != serio)) serioptr = &((*serioptr)->next);
*serioptr = (*serioptr)->next;
if (serio->dev && serio->dev->disconnect)
serio->dev->disconnect(serio);
}
void serio_register_device(struct serio_dev *dev)
{
struct serio *serio = serio_list;
dev->next = serio_dev;
serio_dev = dev;
while (serio) {
if (!serio->dev && dev->connect)
dev->connect(serio, dev);
serio = serio->next;
}
}
void serio_unregister_device(struct serio_dev *dev)
{
struct serio_dev **devptr = &serio_dev;
struct serio *serio = serio_list;
while (*devptr && (*devptr != dev)) devptr = &((*devptr)->next);
*devptr = (*devptr)->next;
while (serio) {
if (serio->dev == dev && dev->disconnect)
dev->disconnect(serio);
serio_find_dev(serio);
serio = serio->next;
}
}
int serio_open(struct serio *serio, struct serio_dev *dev)
{
if (serio->open(serio))
return -1;
serio->dev = dev;
return 0;
}
void serio_close(struct serio *serio)
{
serio->close(serio);
serio->dev = NULL;
}
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 21:00:05
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/usb
In directory usw-pr-cvs1:/tmp/cvs-serv17955
Added Files:
Tag: 1.29
wacom.c
Log Message:
Moved.
--- NEW FILE: wacom.c ---
/*
* $Id: wacom.c,v 1.29 2002/01/22 21:00:01 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik <vo...@uc...>
* Copyright (c) 2000 Andreas Bach Aaen <ab...@st...>
* Copyright (c) 2000 Clifford Wolf <cli...@cl...>
* Copyright (c) 2000 Sam Mosel <sam...@co...>
* Copyright (c) 2000 James E. Blair <co...@gn...>
* Copyright (c) 2000 Daniel Egger <eg...@su...>
* Copyright (c) 2001 Frederic Lepied <fl...@ma...>
*
* USB Wacom Graphire and Wacom Intuos tablet support
*
* ChangeLog:
* v0.1 (vp) - Initial release
* v0.2 (aba) - Support for all buttons / combinations
* v0.3 (vp) - Support for Intuos added
* v0.4 (sm) - Support for more Intuos models, menustrip
* relative mode, proximity.
* v0.5 (vp) - Big cleanup, nifty features removed,
* they belong in userspace
* v1.8 (vp) - Submit URB only when operating, moved to CVS,
* use input_report_key instead of report_btn and
* other cleanups
* v1.11 (vp) - Add URB ->dev setting for new kernels
* v1.11 (jb) - Add support for the 4D Mouse & Lens
* v1.12 (de) - Add support for two more inking pen IDs
* v1.14 (vp) - Use new USB device id probing scheme.
* Fix Wacom Graphire mouse wheel
* v1.18 (vp) - Fix mouse wheel direction
* Make mouse relative
* v1.20 (fl) - Report tool id for Intuos devices
* - Multi tools support
* - Corrected Intuos protocol decoding (airbrush, 4D mouse, lens cursor...)
* - Add PL models support
* - Fix Wacom Graphire mouse wheel again
* v1.21 (vp) - Removed protocol descriptions
* - Added MISC_SERIAL for tool serial numbers
* (gb) - Identify version on module load.
*/
/*
* 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
#include "usbpath.h"
/*
* Version Information
*/
#define DRIVER_VERSION "v1.21"
#define DRIVER_AUTHOR "Vojtech Pavlik <vo...@uc...>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL"
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);
#define USB_VENDOR_ID_WACOM 0x056a
struct wacom_features {
char *name;
int pktlen;
int x_max;
int y_max;
int pressure_max;
int distance_max;
void (*irq)(struct urb *urb);
unsigned long evbit;
unsigned long absbit;
unsigned long relbit;
unsigned long btnbit;
unsigned long digibit;
};
struct wacom {
signed char data[10];
struct input_dev dev;
struct usb_device *usbdev;
struct urb irq;
struct wacom_features *features;
int tool[2];
int open;
int x, y;
__u32 serial[2];
char phys[32];
};
static void wacom_pl_irq(struct urb *urb)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
struct input_dev *dev = &wacom->dev;
int prox;
if (urb->status) return;
if (data[0] != 2)
dbg("received unknown report #%d", data[0]);
prox = data[1] & 0x20;
input_report_key(dev, BTN_TOOL_PEN, prox);
if (prox) {
int pressure = (data[4] & 0x04) >> 2 | ((__u32)(data[7] & 0x7f) << 1);
input_report_abs(dev, ABS_X, data[3] | ((__u32)data[2] << 8) | ((__u32)(data[1] & 0x03) << 16));
input_report_abs(dev, ABS_Y, data[6] | ((__u32)data[5] << 8) | ((__u32)(data[4] & 0x03) << 8));
input_report_abs(dev, ABS_PRESSURE, (data[7] & 0x80) ? (255 - pressure) : (pressure + 255));
input_report_key(dev, BTN_TOUCH, data[4] & 0x08);
input_report_key(dev, BTN_STYLUS, data[4] & 0x10);
input_report_key(dev, BTN_STYLUS2, data[4] & 0x20);
}
input_event(dev, EV_MSC, MSC_SERIAL, 0);
}
static void wacom_graphire_irq(struct urb *urb)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
struct input_dev *dev = &wacom->dev;
int x, y;
if (urb->status) return;
if (data[0] != 2)
dbg("received unknown report #%d", data[0]);
x = data[2] | ((__u32)data[3] << 8);
y = data[4] | ((__u32)data[5] << 8);
switch ((data[1] >> 5) & 3) {
case 0: /* Pen */
input_report_key(dev, BTN_TOOL_PEN, data[1] & 0x80);
break;
case 1: /* Rubber */
input_report_key(dev, BTN_TOOL_RUBBER, data[1] & 0x80);
break;
case 2: /* Mouse */
input_report_key(dev, BTN_TOOL_MOUSE, data[7] > 24);
input_report_key(dev, BTN_LEFT, data[1] & 0x01);
input_report_key(dev, BTN_RIGHT, data[1] & 0x02);
input_report_key(dev, BTN_MIDDLE, data[1] & 0x04);
input_report_abs(dev, ABS_DISTANCE, data[7]);
input_report_rel(dev, REL_WHEEL, (signed char) data[6]);
input_report_abs(dev, ABS_X, x);
input_report_abs(dev, ABS_Y, y);
input_event(dev, EV_MSC, MSC_SERIAL, data[1] & 0x01);
return;
}
if (data[1] & 0x80) {
input_report_abs(dev, ABS_X, wacom->x = x);
input_report_abs(dev, ABS_Y, wacom->y = y);
}
input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8));
input_report_key(dev, BTN_TOUCH, data[1] & 0x01);
input_report_key(dev, BTN_STYLUS, data[1] & 0x02);
input_report_key(dev, BTN_STYLUS2, data[1] & 0x04);
input_event(dev, EV_MSC, MSC_SERIAL, data[1] & 0x01);
}
static void wacom_intuos_irq(struct urb *urb)
{
struct wacom *wacom = urb->context;
unsigned char *data = wacom->data;
struct input_dev *dev = &wacom->dev;
unsigned int t;
int idx;
if (urb->status) return;
if (data[0] != 2)
dbg("received unknown report #%d", data[0]);
/* tool number */
idx = data[1] & 0x01;
if ((data[1] & 0xfc) == 0xc0) { /* Enter report */
wacom->serial[idx] = ((__u32)(data[3] & 0x0f) << 4) + /* serial number of the tool */
((__u32)data[4] << 16) + ((__u32)data[5] << 12) +
((__u32)data[6] << 4) + (data[7] >> 4);
switch (((__u32)data[2] << 4) | (data[3] >> 4)) {
case 0x832:
case 0x012: wacom->tool[idx] = BTN_TOOL_PENCIL; break; /* Inking pen */
case 0x822:
case 0x022: wacom->tool[idx] = BTN_TOOL_PEN; break; /* Pen */
case 0x812:
case 0x032: wacom->tool[idx] = BTN_TOOL_BRUSH; break; /* Stroke pen */
case 0x09c:
case 0x094: wacom->tool[idx] = BTN_TOOL_MOUSE; break; /* Mouse 4D */
case 0x096: wacom->tool[idx] = BTN_TOOL_LENS; break; /* Lens cursor */
case 0x82a:
case 0x91a:
case 0x0fa: wacom->tool[idx] = BTN_TOOL_RUBBER; break; /* Eraser */
case 0x112: wacom->tool[idx] = BTN_TOOL_AIRBRUSH; break; /* Airbrush */
default: wacom->tool[idx] = BTN_TOOL_PEN; break; /* Unknown tool */
}
input_report_key(dev, wacom->tool[idx], 1);
input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
return;
}
if ((data[1] & 0xfe) == 0x80) { /* Exit report */
input_report_key(dev, wacom->tool[idx], 0);
input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
return;
}
input_report_abs(dev, ABS_X, ((__u32)data[2] << 8) | data[3]);
input_report_abs(dev, ABS_Y, ((__u32)data[4] << 8) | data[5]);
input_report_abs(dev, ABS_DISTANCE, data[9] >> 4);
if ((data[1] & 0xb8) == 0xa0) { /* general pen packet */
input_report_abs(dev, ABS_PRESSURE, t = ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
input_report_key(dev, BTN_STYLUS, data[1] & 2);
input_report_key(dev, BTN_STYLUS2, data[1] & 4);
input_report_key(dev, BTN_TOUCH, t > 10);
}
if ((data[1] & 0xbc) == 0xb4) { /* airbrush second packet */
input_report_abs(dev, ABS_WHEEL, ((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
input_report_abs(dev, ABS_TILT_X, ((data[7] << 1) & 0x7e) | (data[8] >> 7));
input_report_abs(dev, ABS_TILT_Y, data[8] & 0x7f);
}
if ((data[1] & 0xbc) == 0xa8 || (data[1] & 0xbe) == 0xb0) { /* 4D mouse or Lens cursor packets */
if (data[1] & 0x02) { /* Rotation packet */
input_report_abs(dev, ABS_RZ, (data[7] & 0x20) ?
((__u32)data[6] << 2) | ((data[7] >> 6) & 3):
(-(((__u32)data[6] << 2) | ((data[7] >> 6) & 3))) - 1);
} else {
input_report_key(dev, BTN_LEFT, data[8] & 0x01);
input_report_key(dev, BTN_MIDDLE, data[8] & 0x02);
input_report_key(dev, BTN_RIGHT, data[8] & 0x04);
if ((data[1] & 0x10) == 0) { /* 4D mouse packets */
input_report_key(dev, BTN_SIDE, data[8] & 0x20);
input_report_key(dev, BTN_EXTRA, data[8] & 0x10);
input_report_abs(dev, ABS_THROTTLE, (data[8] & 0x08) ?
((__u32)data[6] << 2) | ((data[7] >> 6) & 3) :
-((__u32)data[6] << 2) | ((data[7] >> 6) & 3));
} else { /* Lens cursor packets */
input_report_key(dev, BTN_SIDE, data[8] & 0x10);
input_report_key(dev, BTN_EXTRA, data[8] & 0x08);
}
}
}
input_event(dev, EV_MSC, MSC_SERIAL, wacom->serial[idx]);
}
#define WACOM_INTUOS_TOOLS (BIT(BTN_TOOL_BRUSH) | BIT(BTN_TOOL_PENCIL) | BIT(BTN_TOOL_AIRBRUSH) | BIT(BTN_TOOL_LENS))
#define WACOM_INTUOS_BUTTONS (BIT(BTN_SIDE) | BIT(BTN_EXTRA))
#define WACOM_INTUOS_ABS (BIT(ABS_TILT_X) | BIT(ABS_TILT_Y) | BIT(ABS_RZ) | BIT(ABS_THROTTLE))
struct wacom_features wacom_features[] = {
{ "Wacom Graphire", 8, 10206, 7422, 511, 32, wacom_graphire_irq,
BIT(EV_REL), 0, BIT(REL_WHEEL), 0 },
{ "Wacom Intuos 4x5", 10, 12700, 10360, 1023, 15, wacom_intuos_irq,
0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
{ "Wacom Intuos 6x8", 10, 20320, 15040, 1023, 15, wacom_intuos_irq,
0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
{ "Wacom Intuos 9x12", 10, 30480, 23060, 1023, 15, wacom_intuos_irq,
0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
{ "Wacom Intuos 12x12", 10, 30480, 30480, 1023, 15, wacom_intuos_irq,
0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
{ "Wacom Intuos 12x18", 10, 47720, 30480, 1023, 15, wacom_intuos_irq,
0, WACOM_INTUOS_ABS, 0, WACOM_INTUOS_BUTTONS, WACOM_INTUOS_TOOLS },
{ "Wacom PL500", 8, 12328, 9256, 511, 32, wacom_pl_irq,
0, 0, 0, 0 },
{ NULL , 0 }
};
struct usb_device_id wacom_ids[] = {
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x10), driver_info: 0 },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x20), driver_info: 1 },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x21), driver_info: 2 },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x22), driver_info: 3 },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x23), driver_info: 4 },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x24), driver_info: 5 },
{ USB_DEVICE(USB_VENDOR_ID_WACOM, 0x31), driver_info: 6 },
{ }
};
MODULE_DEVICE_TABLE(usb, wacom_ids);
static int wacom_open(struct input_dev *dev)
{
struct wacom *wacom = dev->private;
if (wacom->open++)
return 0;
wacom->irq.dev = wacom->usbdev;
if (usb_submit_urb(&wacom->irq))
return -EIO;
return 0;
}
static void wacom_close(struct input_dev *dev)
{
struct wacom *wacom = dev->private;
if (!--wacom->open)
usb_unlink_urb(&wacom->irq);
}
static void *wacom_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id)
{
struct usb_endpoint_descriptor *endpoint;
struct wacom *wacom;
char path[64];
if (!(wacom = kmalloc(sizeof(struct wacom), GFP_KERNEL))) return NULL;
memset(wacom, 0, sizeof(struct wacom));
wacom->features = wacom_features + id->driver_info;
wacom->dev.evbit[0] |= BIT(EV_KEY) | BIT(EV_ABS) | BIT(EV_MSC) | wacom->features->evbit;
wacom->dev.absbit[0] |= BIT(ABS_X) | BIT(ABS_Y) | BIT(ABS_PRESSURE) | BIT(ABS_DISTANCE) | BIT(ABS_WHEEL) | wacom->features->absbit;
wacom->dev.relbit[0] |= wacom->features->relbit;
wacom->dev.keybit[LONG(BTN_LEFT)] |= BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE) | wacom->features->btnbit;
wacom->dev.keybit[LONG(BTN_DIGI)] |= BIT(BTN_TOOL_PEN) | BIT(BTN_TOOL_RUBBER) | BIT(BTN_TOOL_MOUSE) |
BIT(BTN_TOUCH) | BIT(BTN_STYLUS) | BIT(BTN_STYLUS2) | wacom->features->digibit;
wacom->dev.mscbit[0] |= BIT(MSC_SERIAL);
wacom->dev.absmax[ABS_X] = wacom->features->x_max;
wacom->dev.absmax[ABS_Y] = wacom->features->y_max;
wacom->dev.absmax[ABS_PRESSURE] = wacom->features->pressure_max;
wacom->dev.absmax[ABS_DISTANCE] = wacom->features->distance_max;
wacom->dev.absmax[ABS_TILT_X] = 127;
wacom->dev.absmax[ABS_TILT_Y] = 127;
wacom->dev.absmax[ABS_WHEEL] = 1023;
wacom->dev.absmin[ABS_RZ] = -900;
wacom->dev.absmax[ABS_RZ] = 899;
wacom->dev.absmin[ABS_THROTTLE] = -1023;
wacom->dev.absmax[ABS_THROTTLE] = 1023;
wacom->dev.absfuzz[ABS_X] = 4;
wacom->dev.absfuzz[ABS_Y] = 4;
wacom->dev.private = wacom;
wacom->dev.open = wacom_open;
wacom->dev.close = wacom_close;
usb_make_path(dev, path, 64);
sprintf(wacom->phys, "%s/input0", path);
wacom->dev.name = wacom->features->name;
wacom->dev.phys = wacom->phys;
wacom->dev.idbus = BUS_USB;
wacom->dev.idvendor = dev->descriptor.idVendor;
wacom->dev.idproduct = dev->descriptor.idProduct;
wacom->dev.idversion = dev->descriptor.bcdDevice;
wacom->usbdev = dev;
endpoint = dev->config[0].interface[ifnum].altsetting[0].endpoint + 0;
FILL_INT_URB(&wacom->irq, dev, usb_rcvintpipe(dev, endpoint->bEndpointAddress),
wacom->data, wacom->features->pktlen, wacom->features->irq, wacom, endpoint->bInterval);
input_register_device(&wacom->dev);
printk(KERN_INFO "input: %s on %s\n", wacom->features->name, path);
return wacom;
}
static void wacom_disconnect(struct usb_device *dev, void *ptr)
{
struct wacom *wacom = ptr;
usb_unlink_urb(&wacom->irq);
input_unregister_device(&wacom->dev);
kfree(wacom);
}
static struct usb_driver wacom_driver = {
name: "wacom",
probe: wacom_probe,
disconnect: wacom_disconnect,
id_table: wacom_ids,
};
static int __init wacom_init(void)
{
usb_register(&wacom_driver);
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
}
static void __exit wacom_exit(void)
{
usb_deregister(&wacom_driver);
}
module_init(wacom_init);
module_exit(wacom_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:59:47
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/usb
In directory usw-pr-cvs1:/tmp/cvs-serv17860
Added Files:
Tag: 1
usbpath.h
Log Message:
Moved.
--- NEW FILE: usbpath.h ---
static int usb_make_path(struct usb_device *dev, char *buf, int maxlen)
{
struct usb_device *pdev = dev->parent;
char *tmp, *port;
int i;
if (!(port = kmalloc(maxlen, GFP_KERNEL)))
return -1;
if (!(tmp = kmalloc(maxlen, GFP_KERNEL)))
return -1;
*port = 0;
while (pdev) {
for (i = 0; i < pdev->maxchild; i++)
if (pdev->children[i] == dev)
break;
if (pdev->children[i] != dev)
return -1;
strcpy(tmp, port);
sprintf(port, strlen(port) ? "%d.%s" : "%d", i + 1, tmp);
dev = pdev;
pdev = dev->parent;
}
sprintf(buf, "usb%d:%s", dev->bus->busnum, port);
return 0;
}
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:59:32
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/usb
In directory usw-pr-cvs1:/tmp/cvs-serv17788
Added Files:
Tag: 1.16
usbmouse.c
Log Message:
Moved.
--- NEW FILE: usbmouse.c ---
/*
* $Id: usbmouse.c,v 1.16 2002/01/22 20:59:30 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* USB HIDBP Mouse support
*/
/*
* 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
#include "usbpath.h"
/*
* Version Information
*/
#define DRIVER_VERSION "v1.6"
#define DRIVER_AUTHOR "Vojtech Pavlik <vo...@uc...>"
#define DRIVER_DESC "USB HID Boot Protocol mouse driver"
#define DRIVER_LICENSE "GPL"
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);
struct usb_mouse {
signed char data[8];
char name[128];
char phys[64];
struct usb_device *usbdev;
struct input_dev dev;
struct urb irq;
int open;
};
static void usb_mouse_irq(struct urb *urb)
{
struct usb_mouse *mouse = urb->context;
signed char *data = mouse->data;
struct input_dev *dev = &mouse->dev;
if (urb->status) return;
input_report_key(dev, BTN_LEFT, data[0] & 0x01);
input_report_key(dev, BTN_RIGHT, data[0] & 0x02);
input_report_key(dev, BTN_MIDDLE, data[0] & 0x04);
input_report_key(dev, BTN_SIDE, data[0] & 0x08);
input_report_key(dev, BTN_EXTRA, data[0] & 0x10);
input_report_rel(dev, REL_X, data[1]);
input_report_rel(dev, REL_Y, data[2]);
input_report_rel(dev, REL_WHEEL, data[3]);
}
static int usb_mouse_open(struct input_dev *dev)
{
struct usb_mouse *mouse = dev->private;
if (mouse->open++)
return 0;
mouse->irq.dev = mouse->usbdev;
if (usb_submit_urb(&mouse->irq))
return -EIO;
return 0;
}
static void usb_mouse_close(struct input_dev *dev)
{
struct usb_mouse *mouse = dev->private;
if (!--mouse->open)
usb_unlink_urb(&mouse->irq);
}
static void *usb_mouse_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
struct usb_interface *iface;
struct usb_interface_descriptor *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_mouse *mouse;
int pipe, maxp;
char path[64];
char *buf;
iface = &dev->actconfig->interface[ifnum];
interface = &iface->altsetting[iface->act_altsetting];
if (interface->bNumEndpoints != 1) return NULL;
endpoint = interface->endpoint + 0;
if (!(endpoint->bEndpointAddress & 0x80)) return NULL;
if ((endpoint->bmAttributes & 3) != 3) return NULL;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
if (!(mouse = kmalloc(sizeof(struct usb_mouse), GFP_KERNEL))) return NULL;
memset(mouse, 0, sizeof(struct usb_mouse));
mouse->usbdev = dev;
mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
mouse->dev.keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
mouse->dev.relbit[0] |= BIT(REL_WHEEL);
mouse->dev.private = mouse;
mouse->dev.open = usb_mouse_open;
mouse->dev.close = usb_mouse_close;
usb_make_path(dev, path, 64);
sprintf(mouse->phys, "%s/input0", path);
mouse->dev.name = mouse->name;
mouse->dev.phys = mouse->phys;
mouse->dev.idbus = BUS_USB;
mouse->dev.idvendor = dev->descriptor.idVendor;
mouse->dev.idproduct = dev->descriptor.idProduct;
mouse->dev.idversion = dev->descriptor.bcdDevice;
if (!(buf = kmalloc(63, GFP_KERNEL))) {
kfree(mouse);
return NULL;
}
if (dev->descriptor.iManufacturer &&
usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
strcat(mouse->name, buf);
if (dev->descriptor.iProduct &&
usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
sprintf(mouse->name, "%s %s", mouse->name, buf);
if (!strlen(mouse->name))
sprintf(mouse->name, "USB HIDBP Mouse %04x:%04x",
mouse->dev.idvendor, mouse->dev.idproduct);
kfree(buf);
FILL_INT_URB(&mouse->irq, dev, pipe, mouse->data, maxp > 8 ? 8 : maxp,
usb_mouse_irq, mouse, endpoint->bInterval);
input_register_device(&mouse->dev);
printk(KERN_INFO "input: %s on %s\n", mouse->name, path);
return mouse;
}
static void usb_mouse_disconnect(struct usb_device *dev, void *ptr)
{
struct usb_mouse *mouse = ptr;
usb_unlink_urb(&mouse->irq);
input_unregister_device(&mouse->dev);
kfree(mouse);
}
static struct usb_device_id usb_mouse_id_table [] = {
{ USB_INTERFACE_INFO(3, 1, 2) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, usb_mouse_id_table);
static struct usb_driver usb_mouse_driver = {
name: "usb_mouse",
probe: usb_mouse_probe,
disconnect: usb_mouse_disconnect,
id_table: usb_mouse_id_table,
};
static int __init usb_mouse_init(void)
{
usb_register(&usb_mouse_driver);
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
}
static void __exit usb_mouse_exit(void)
{
usb_deregister(&usb_mouse_driver);
}
module_init(usb_mouse_init);
module_exit(usb_mouse_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:59:19
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/usb
In directory usw-pr-cvs1:/tmp/cvs-serv17724
Added Files:
Tag: 1.30
usbkbd.c
Log Message:
Moved.
--- NEW FILE: usbkbd.c ---
/*
* $Id: usbkbd.c,v 1.30 2002/01/22 20:59:16 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* USB HIDBP Keyboard support
*
* Sponsored by SuSE
*/
/*
* 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 <vo...@su...>, or by paper mail:
* Vojtech Pavlik, Ucitelska 1576, Prague 8, 182 00 Czech Republic
*/
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/usb.h>
#define _HID_BOOT_PROTOCOL
#include "hid.h"
/*
* Version Information
*/
#define DRIVER_VERSION ""
#define DRIVER_AUTHOR "Vojtech Pavlik <vo...@su...>"
#define DRIVER_DESC "USB HID Boot Protocol keyboard driver"
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_LICENSE("GPL");
static unsigned char usb_kbd_keycode[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
115,114, 0, 0, 0,124, 0,181,182,183,184,185,186,187,188,189,
190,191,192,193,194,195,196,197,198, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
150,158,159,128,136,177,178,176,142,152,173,140
};
struct usb_kbd {
struct input_dev dev;
struct usb_device *usbdev;
unsigned char new[8];
unsigned char old[8];
struct urb irq, led;
struct usb_ctrlrequest dr;
unsigned char leds, newleds;
char name[128];
int open;
};
static void usb_kbd_irq(struct urb *urb)
{
struct usb_kbd *kbd = urb->context;
int i;
if (urb->status) return;
for (i = 0; i < 8; i++)
input_report_key(&kbd->dev, usb_kbd_keycode[i + 224], (kbd->new[0] >> i) & 1);
for (i = 2; i < 8; i++) {
if (kbd->old[i] > 3 && memscan(kbd->new + 2, kbd->old[i], 6) == kbd->new + 8) {
if (usb_kbd_keycode[kbd->old[i]])
input_report_key(&kbd->dev, usb_kbd_keycode[kbd->old[i]], 0);
else
info("Unknown key (scancode %#x) released.", kbd->old[i]);
}
if (kbd->new[i] > 3 && memscan(kbd->old + 2, kbd->new[i], 6) == kbd->old + 8) {
if (usb_kbd_keycode[kbd->new[i]])
input_report_key(&kbd->dev, usb_kbd_keycode[kbd->new[i]], 1);
else
info("Unknown key (scancode %#x) pressed.", kbd->new[i]);
}
}
memcpy(kbd->old, kbd->new, 8);
}
int usb_kbd_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct usb_kbd *kbd = dev->private;
if (type != EV_LED) return -1;
kbd->newleds = (!!test_bit(LED_KANA, dev->led) << 3) | (!!test_bit(LED_COMPOSE, dev->led) << 3) |
(!!test_bit(LED_SCROLLL, dev->led) << 2) | (!!test_bit(LED_CAPSL, dev->led) << 1) |
(!!test_bit(LED_NUML, dev->led));
if (kbd->led.status == -EINPROGRESS)
return 0;
if (kbd->leds == kbd->newleds)
return 0;
kbd->leds = kbd->newleds;
kbd->led.dev = kbd->usbdev;
if (usb_submit_urb(&kbd->led))
err("usb_submit_urb(leds) failed");
return 0;
}
static void usb_kbd_led(struct urb *urb)
{
struct usb_kbd *kbd = urb->context;
if (urb->status)
warn("led urb status %d received", urb->status);
if (kbd->leds == kbd->newleds)
return;
kbd->leds = kbd->newleds;
kbd->led.dev = kbd->usbdev;
if (usb_submit_urb(&kbd->led))
err("usb_submit_urb(leds) failed");
}
static int usb_kbd_open(struct input_dev *dev)
{
struct usb_kbd *kbd = dev->private;
if (kbd->open++)
return 0;
kbd->irq.dev = kbd->usbdev;
if (usb_submit_urb(&kbd->irq))
return -EIO;
return 0;
}
static void usb_kbd_close(struct input_dev *dev)
{
struct usb_kbd *kbd = dev->private;
if (!--kbd->open)
usb_unlink_urb(&kbd->irq);
}
static void *usb_kbd_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *id)
{
struct usb_interface *iface;
struct usb_interface_descriptor *interface;
struct usb_endpoint_descriptor *endpoint;
struct usb_kbd *kbd;
int i, pipe, maxp;
char *buf;
iface = &dev->actconfig->interface[ifnum];
interface = &iface->altsetting[iface->act_altsetting];
if (interface->bNumEndpoints != 1) return NULL;
endpoint = interface->endpoint + 0;
if (!(endpoint->bEndpointAddress & 0x80)) return NULL;
if ((endpoint->bmAttributes & 3) != 3) return NULL;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe));
hid_set_protocol(dev, interface->bInterfaceNumber, 0);
hid_set_idle(dev, interface->bInterfaceNumber, 0, 0);
if (!(kbd = kmalloc(sizeof(struct usb_kbd), GFP_KERNEL))) return NULL;
memset(kbd, 0, sizeof(struct usb_kbd));
kbd->usbdev = dev;
kbd->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_LED) | BIT(EV_REP);
kbd->dev.ledbit[0] = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL) | BIT(LED_COMPOSE) | BIT(LED_KANA);
for (i = 0; i < 255; i++)
set_bit(usb_kbd_keycode[i], kbd->dev.keybit);
clear_bit(0, kbd->dev.keybit);
kbd->dev.private = kbd;
kbd->dev.event = usb_kbd_event;
kbd->dev.open = usb_kbd_open;
kbd->dev.close = usb_kbd_close;
FILL_INT_URB(&kbd->irq, dev, pipe, kbd->new, maxp > 8 ? 8 : maxp,
usb_kbd_irq, kbd, endpoint->bInterval);
kbd->dr.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
kbd->dr.bRequest = HID_REQ_SET_REPORT;
kbd->dr.wValue = 0x200;
kbd->dr.wIndex = interface->bInterfaceNumber;
kbd->dr.wLength = 1;
kbd->dev.name = kbd->name;
kbd->dev.idbus = BUS_USB;
kbd->dev.idvendor = dev->descriptor.idVendor;
kbd->dev.idproduct = dev->descriptor.idProduct;
kbd->dev.idversion = dev->descriptor.bcdDevice;
if (!(buf = kmalloc(63, GFP_KERNEL))) {
kfree(kbd);
return NULL;
}
if (dev->descriptor.iManufacturer &&
usb_string(dev, dev->descriptor.iManufacturer, buf, 63) > 0)
strcat(kbd->name, buf);
if (dev->descriptor.iProduct &&
usb_string(dev, dev->descriptor.iProduct, buf, 63) > 0)
sprintf(kbd->name, "%s %s", kbd->name, buf);
if (!strlen(kbd->name))
sprintf(kbd->name, "USB HIDBP Keyboard %04x:%04x",
kbd->dev.idvendor, kbd->dev.idproduct);
kfree(buf);
FILL_CONTROL_URB(&kbd->led, dev, usb_sndctrlpipe(dev, 0),
(void*) &kbd->dr, &kbd->leds, 1, usb_kbd_led, kbd);
input_register_device(&kbd->dev);
printk(KERN_INFO "input%d: %s on usb%d:%d.%d\n",
kbd->dev.number, kbd->name, dev->bus->busnum, dev->devnum, ifnum);
return kbd;
}
static void usb_kbd_disconnect(struct usb_device *dev, void *ptr)
{
struct usb_kbd *kbd = ptr;
usb_unlink_urb(&kbd->irq);
input_unregister_device(&kbd->dev);
kfree(kbd);
}
static struct usb_device_id usb_kbd_id_table [] = {
{ USB_INTERFACE_INFO(3, 1, 1) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, usb_kbd_id_table);
static struct usb_driver usb_kbd_driver = {
name: "keyboard",
probe: usb_kbd_probe,
disconnect: usb_kbd_disconnect,
id_table: usb_kbd_id_table,
};
static int __init usb_kbd_init(void)
{
usb_register(&usb_kbd_driver);
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
}
static void __exit usb_kbd_exit(void)
{
usb_deregister(&usb_kbd_driver);
}
module_init(usb_kbd_init);
module_exit(usb_kbd_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:59:01
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/usb
In directory usw-pr-cvs1:/tmp/cvs-serv17619
Added Files:
Tag: 1
hiddev.c
Log Message:
Moved.
--- NEW FILE: hiddev.c ---
/*
* Copyright (c) 2001 Paul Stewart
* Copyright (c) 2001 Vojtech Pavlik
*
* HID char devices, giving access to raw HID device events.
*
*/
/*
* 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 Paul Stewart <st...@we...>
*/
#define HIDDEV_MINOR_BASE 96
#define HIDDEV_MINORS 16
#define HIDDEV_BUFFER_SIZE 64
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/smp_lock.h>
#include <linux/input.h>
#include <linux/usb.h>
#include "hid.h"
#include <linux/hiddev.h>
struct hiddev {
int exist;
int open;
int minor;
wait_queue_head_t wait;
devfs_handle_t devfs;
struct hid_device *hid;
struct hiddev_list *list;
};
struct hiddev_list {
struct hiddev_event buffer[HIDDEV_BUFFER_SIZE];
int head;
int tail;
struct fasync_struct *fasync;
struct hiddev *hiddev;
struct hiddev_list *next;
};
static struct hiddev *hiddev_table[HIDDEV_MINORS];
static devfs_handle_t hiddev_devfs_handle;
/*
* Find a report, given the report's type and ID. The ID can be specified
* indirectly by REPORT_ID_FIRST (which returns the first report of the given
* type) or by (REPORT_ID_NEXT | old_id), which returns the next report of the
* given type which follows old_id.
*/
static struct hid_report *
hiddev_lookup_report(struct hid_device *hid, struct hiddev_report_info *rinfo)
{
struct hid_report_enum *report_enum;
struct list_head *list;
if (rinfo->report_type < HID_REPORT_TYPE_MIN ||
rinfo->report_type > HID_REPORT_TYPE_MAX) return NULL;
report_enum = hid->report_enum +
(rinfo->report_type - HID_REPORT_TYPE_MIN);
if ((rinfo->report_id & ~HID_REPORT_ID_MASK) != 0) {
switch (rinfo->report_id & ~HID_REPORT_ID_MASK) {
case HID_REPORT_ID_FIRST:
list = report_enum->report_list.next;
if (list == &report_enum->report_list) return NULL;
rinfo->report_id = ((struct hid_report *) list)->id;
break;
case HID_REPORT_ID_NEXT:
list = (struct list_head *)
report_enum->report_id_hash[rinfo->report_id &
HID_REPORT_ID_MASK];
if (list == NULL) return NULL;
list = list->next;
if (list == &report_enum->report_list) return NULL;
rinfo->report_id = ((struct hid_report *) list)->id;
break;
default:
return NULL;
}
}
return report_enum->report_id_hash[rinfo->report_id];
}
/*
* Perform an exhaustive search of the report table for a usage, given its
* type and usage id.
*/
static struct hid_field *
hiddev_lookup_usage(struct hid_device *hid, struct hiddev_usage_ref *uref)
{
int i, j;
struct hid_report *report;
struct hid_report_enum *report_enum;
struct list_head *list;
struct hid_field *field;
if (uref->report_type < HID_REPORT_TYPE_MIN ||
uref->report_type > HID_REPORT_TYPE_MAX) return NULL;
report_enum = hid->report_enum +
(uref->report_type - HID_REPORT_TYPE_MIN);
list = report_enum->report_list.next;
while (list != &report_enum->report_list) {
report = (struct hid_report *) list;
for (i = 0; i < report->maxfield; i++) {
field = report->field[i];
for (j = 0; j < field->maxusage; j++) {
if (field->usage[j].hid == uref->usage_code) {
uref->report_id = report->id;
uref->field_index = i;
uref->usage_index = j;
return field;
}
}
}
list = list->next;
}
return NULL;
}
/*
* This is where hid.c calls into hiddev to pass an event that occurred over
* the interrupt pipe
*/
void hiddev_hid_event(struct hid_device *hid, unsigned int usage, int value)
{
struct hiddev *hiddev = hid->hiddev;
struct hiddev_list *list = hiddev->list;
while (list) {
list->buffer[list->head].hid = usage;
list->buffer[list->head].value = value;
list->head = (list->head + 1) & (HIDDEV_BUFFER_SIZE - 1);
kill_fasync(&list->fasync, SIGIO, POLL_IN);
list = list->next;
}
wake_up_interruptible(&hiddev->wait);
}
/*
* fasync file op
*/
static int hiddev_fasync(int fd, struct file *file, int on)
{
int retval;
struct hiddev_list *list = file->private_data;
retval = fasync_helper(fd, file, on, &list->fasync);
return retval < 0 ? retval : 0;
}
/*
* De-allocate a hiddev structure
*/
static void hiddev_cleanup(struct hiddev *hiddev)
{
devfs_unregister(hiddev->devfs);
hiddev_table[hiddev->minor] = NULL;
kfree(hiddev);
}
/*
* release file op
*/
static int hiddev_release(struct inode * inode, struct file * file)
{
struct hiddev_list *list = file->private_data;
struct hiddev_list **listptr;
listptr = &list->hiddev->list;
hiddev_fasync(-1, file, 0);
while (*listptr && (*listptr != list))
listptr = &((*listptr)->next);
*listptr = (*listptr)->next;
if (!--list->hiddev->open) {
if (list->hiddev->exist)
hid_close(list->hiddev->hid);
else
hiddev_cleanup(list->hiddev);
}
kfree(list);
return 0;
}
/*
* open file op
*/
static int hiddev_open(struct inode * inode, struct file * file) {
struct hiddev_list *list;
int i = minor(inode->i_rdev) - HIDDEV_MINOR_BASE;
if (i >= HIDDEV_MINORS || !hiddev_table[i])
return -ENODEV;
if (!(list = kmalloc(sizeof(struct hiddev_list), GFP_KERNEL)))
return -ENOMEM;
memset(list, 0, sizeof(struct hiddev_list));
list->hiddev = hiddev_table[i];
list->next = hiddev_table[i]->list;
hiddev_table[i]->list = list;
file->private_data = list;
if (!list->hiddev->open++)
if (list->hiddev->exist)
hid_open(hiddev_table[i]->hid);
return 0;
}
/*
* "write" file op
*/
static ssize_t hiddev_write(struct file * file, const char * buffer,
size_t count, loff_t *ppos)
{
return -EINVAL;
}
/*
* "read" file op
*/
static ssize_t hiddev_read(struct file * file, char * buffer, size_t count,
loff_t *ppos)
{
DECLARE_WAITQUEUE(wait, current);
struct hiddev_list *list = file->private_data;
int retval = 0;
if (list->head == list->tail) {
add_wait_queue(&list->hiddev->wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
while (list->head == list->tail) {
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
}
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
if (!list->hiddev->exist) {
retval = -EIO;
break;
}
schedule();
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&list->hiddev->wait, &wait);
}
if (retval)
return retval;
while (list->head != list->tail && retval + sizeof(struct hiddev_event) <= count) {
if (copy_to_user(buffer + retval, list->buffer + list->tail,
sizeof(struct hiddev_event))) return -EFAULT;
list->tail = (list->tail + 1) & (HIDDEV_BUFFER_SIZE - 1);
retval += sizeof(struct hiddev_event);
}
return retval;
}
/*
* "poll" file op
* No kernel lock - fine
*/
static unsigned int hiddev_poll(struct file *file, poll_table *wait)
{
struct hiddev_list *list = file->private_data;
poll_wait(file, &list->hiddev->wait, wait);
if (list->head != list->tail)
return POLLIN | POLLRDNORM;
if (!list->hiddev->exist)
return POLLERR | POLLHUP;
return 0;
}
#define GET_TIMEOUT 3
#define SET_TIMEOUT 3
/*
* "ioctl" file op
*/
static int hiddev_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
struct hiddev_list *list = file->private_data;
struct hiddev *hiddev = list->hiddev;
struct hid_device *hid = hiddev->hid;
struct usb_device *dev = hid->dev;
struct hiddev_report_info rinfo;
struct hiddev_usage_ref uref;
struct hid_report *report;
struct hid_field *field;
if (!hiddev->exist) return -EIO;
switch (cmd) {
case HIDIOCGVERSION:
return put_user(HID_VERSION, (int *) arg);
case HIDIOCAPPLICATION:
if (arg < 0 || arg >= hid->maxapplication)
return -EINVAL;
return hid->application[arg];
case HIDIOCGDEVINFO:
{
struct hiddev_devinfo dinfo;
dinfo.bustype = BUS_USB;
dinfo.busnum = dev->bus->busnum;
dinfo.devnum = dev->devnum;
dinfo.ifnum = hid->ifnum;
dinfo.vendor = dev->descriptor.idVendor;
dinfo.product = dev->descriptor.idProduct;
dinfo.version = dev->descriptor.bcdDevice;
dinfo.num_applications = hid->maxapplication;
return copy_to_user((void *) arg, &dinfo, sizeof(dinfo));
}
case HIDIOCGSTRING:
{
int idx, len;
char *buf;
if (get_user(idx, (int *) arg))
return -EFAULT;
if ((buf = kmalloc(HID_STRING_SIZE, GFP_KERNEL)) == NULL)
return -ENOMEM;
if ((len = usb_string(dev, idx, buf, HID_STRING_SIZE-1)) < 0) {
kfree(buf);
return -EINVAL;
}
if (copy_to_user((void *) (arg+sizeof(int)), buf, len+1)) {
kfree(buf);
return -EFAULT;
}
kfree(buf);
return len;
}
case HIDIOCINITREPORT:
hid_init_reports(hid);
return 0;
case HIDIOCGREPORT:
if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
return -EFAULT;
if (rinfo.report_type == HID_REPORT_TYPE_OUTPUT)
return -EINVAL;
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
hid_submit_report(hid, report, USB_DIR_IN);
return 0;
case HIDIOCSREPORT:
if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
return -EFAULT;
if (rinfo.report_type == HID_REPORT_TYPE_INPUT)
return -EINVAL;
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
hid_submit_report(hid, report, USB_DIR_OUT);
return 0;
case HIDIOCGREPORTINFO:
if (copy_from_user(&rinfo, (void *) arg, sizeof(rinfo)))
return -EFAULT;
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
rinfo.num_fields = report->maxfield;
return copy_to_user((void *) arg, &rinfo, sizeof(rinfo));
case HIDIOCGFIELDINFO:
{
struct hiddev_field_info finfo;
if (copy_from_user(&finfo, (void *) arg, sizeof(finfo)))
return -EFAULT;
rinfo.report_type = finfo.report_type;
rinfo.report_id = finfo.report_id;
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
if (finfo.field_index >= report->maxfield)
return -EINVAL;
field = report->field[finfo.field_index];
memset(&finfo, 0, sizeof(finfo));
finfo.report_type = rinfo.report_type;
finfo.report_id = rinfo.report_id;
finfo.field_index = field->report_count - 1;
finfo.maxusage = field->maxusage;
finfo.flags = field->flags;
finfo.physical = field->physical;
finfo.logical = field->logical;
finfo.application = field->application;
finfo.logical_minimum = field->logical_minimum;
finfo.logical_maximum = field->logical_maximum;
finfo.physical_minimum = field->physical_minimum;
finfo.physical_maximum = field->physical_maximum;
finfo.unit_exponent = field->unit_exponent;
finfo.unit = field->unit;
return copy_to_user((void *) arg, &finfo, sizeof(finfo));
}
case HIDIOCGUCODE:
if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
return -EFAULT;
rinfo.report_type = uref.report_type;
rinfo.report_id = uref.report_id;
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
if (uref.field_index >= report->maxfield)
return -EINVAL;
field = report->field[uref.field_index];
if (uref.usage_index >= field->maxusage)
return -EINVAL;
uref.usage_code = field->usage[uref.usage_index].hid;
return copy_to_user((void *) arg, &uref, sizeof(uref));
case HIDIOCGUSAGE:
if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
return -EFAULT;
if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
field = hiddev_lookup_usage(hid, &uref);
if (field == NULL)
return -EINVAL;
} else {
rinfo.report_type = uref.report_type;
rinfo.report_id = uref.report_id;
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
if (uref.field_index >= report->maxfield)
return -EINVAL;
field = report->field[uref.field_index];
if (uref.usage_index >= field->maxusage)
return -EINVAL;
}
uref.value = field->value[uref.usage_index];
return copy_to_user((void *) arg, &uref, sizeof(uref));
case HIDIOCSUSAGE:
if (copy_from_user(&uref, (void *) arg, sizeof(uref)))
return -EFAULT;
if (uref.report_type == HID_REPORT_TYPE_INPUT)
return -EINVAL;
if (uref.report_id == HID_REPORT_ID_UNKNOWN) {
field = hiddev_lookup_usage(hid, &uref);
if (field == NULL)
return -EINVAL;
} else {
rinfo.report_type = uref.report_type;
rinfo.report_id = uref.report_id;
if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
return -EINVAL;
if (uref.field_index >= report->maxfield)
return -EINVAL;
field = report->field[uref.field_index];
if (uref.usage_index >= field->maxusage)
return -EINVAL;
}
field->value[uref.usage_index] = uref.value;
return 0;
default:
if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ)
return -EINVAL;
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGNAME(0))) {
int len;
if (!hid->name) return 0;
len = strlen(hid->name) + 1;
if (len > _IOC_SIZE(cmd)) len = _IOC_SIZE(cmd);
return copy_to_user((char *) arg, hid->name, len) ?
-EFAULT : len;
}
}
return -EINVAL;
}
static struct file_operations hiddev_fops = {
owner: THIS_MODULE,
read: hiddev_read,
write: hiddev_write,
poll: hiddev_poll,
open: hiddev_open,
release: hiddev_release,
ioctl: hiddev_ioctl,
fasync: hiddev_fasync,
};
/*
* This is where hid.c calls us to connect a hid device to the hiddev driver
*/
int hiddev_connect(struct hid_device *hid)
{
struct hiddev *hiddev;
int minor, i;
char devfs_name[16];
for (i = 0; i < hid->maxapplication; i++)
if (!IS_INPUT_APPLICATION(hid->application[i]))
break;
if (i == hid->maxapplication)
return -1;
for (minor = 0; minor < HIDDEV_MINORS && hiddev_table[minor]; minor++);
if (minor == HIDDEV_MINORS) {
printk(KERN_ERR "hiddev: no more free hiddev devices\n");
return -1;
}
if (!(hiddev = kmalloc(sizeof(struct hiddev), GFP_KERNEL)))
return -1;
memset(hiddev, 0, sizeof(struct hiddev));
init_waitqueue_head(&hiddev->wait);
hiddev->minor = minor;
hiddev_table[minor] = hiddev;
hiddev->hid = hid;
hiddev->exist = 1;
sprintf(devfs_name, "hiddev%d", minor);
hiddev->devfs = devfs_register(hiddev_devfs_handle, devfs_name,
DEVFS_FL_DEFAULT, USB_MAJOR,
minor + HIDDEV_MINOR_BASE,
S_IFCHR | S_IRUGO | S_IWUSR,
&hiddev_fops, NULL);
hid->minor = minor;
hid->hiddev = hiddev;
return 0;
}
/*
* This is where hid.c calls us to disconnect a hiddev device from the
* corresponding hid device (usually because the usb device has disconnected)
*/
void hiddev_disconnect(struct hid_device *hid)
{
struct hiddev *hiddev = hid->hiddev;
hiddev->exist = 0;
if (hiddev->open) {
hid_close(hiddev->hid);
wake_up_interruptible(&hiddev->wait);
} else {
hiddev_cleanup(hiddev);
}
}
/* Currently this driver is a USB driver. It's not a conventional one in
* the sense that it doesn't probe at the USB level. Instead it waits to
* be connected by HID through the hiddev_connect / hiddev_disconnect
* routines. The reason to register as a USB device is to gain part of the
* minor number space from the USB major.
*
* In theory, should the HID code be generalized to more than one physical
* medium (say, IEEE 1384), this driver will probably need to register its
* own major number, and in doing so, no longer need to register with USB.
* At that point the probe routine and hiddev_driver struct below will no
* longer be useful.
*/
/* We never attach in this manner, and rely on HID to connect us. This
* is why there is no disconnect routine defined in the usb_driver either.
*/
static void *hiddev_usbd_probe(struct usb_device *dev, unsigned int ifnum,
const struct usb_device_id *hiddev_info)
{
return NULL;
}
static /* const */ struct usb_driver hiddev_driver = {
name: "hiddev",
probe: hiddev_usbd_probe,
fops: &hiddev_fops,
minor: HIDDEV_MINOR_BASE
};
int __init hiddev_init(void)
{
hiddev_devfs_handle =
devfs_mk_dir(devfs_find_handle(NULL, "usb", 0, 0, 0, 0), "hid", NULL);
usb_register(&hiddev_driver);
return 0;
}
void __exit hiddev_exit(void)
{
devfs_unregister(hiddev_devfs_handle);
usb_deregister(&hiddev_driver);
}
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:57:26
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/usb
In directory usw-pr-cvs1:/tmp/cvs-serv17203
Added Files:
Tag: 1.26
hid.h
Log Message:
Moved.
--- NEW FILE: hid.h ---
#ifndef __HID_H
#define __HID_H
/*
* $Id: hid.h,v 1.26 2002/01/22 20:57:23 vojtech Exp $
*
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2001 Vojtech Pavlik
*/
/*
* 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/list.h>
/*
* USB HID (Human Interface Device) interface class code
*/
#define USB_INTERFACE_CLASS_HID 3
/*
* HID class requests
*/
#define HID_REQ_GET_REPORT 0x01
#define HID_REQ_GET_IDLE 0x02
#define HID_REQ_GET_PROTOCOL 0x03
#define HID_REQ_SET_REPORT 0x09
#define HID_REQ_SET_IDLE 0x0A
#define HID_REQ_SET_PROTOCOL 0x0B
/*
* HID class descriptor types
*/
#define HID_DT_HID (USB_TYPE_CLASS | 0x01)
#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02)
#define HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
/*
* We parse each description item into this structure. Short items data
* values are expanded to 32-bit signed int, long items contain a pointer
* into the data area.
*/
struct hid_item {
unsigned format;
__u8 size;
__u8 type;
__u8 tag;
union {
__u8 u8;
__s8 s8;
__u16 u16;
__s16 s16;
__u32 u32;
__s32 s32;
__u8 *longdata;
} data;
};
/*
* HID report item format
*/
#define HID_ITEM_FORMAT_SHORT 0
#define HID_ITEM_FORMAT_LONG 1
/*
* Special tag indicating long items
*/
#define HID_ITEM_TAG_LONG 15
/*
* HID report descriptor item type (prefix bit 2,3)
*/
#define HID_ITEM_TYPE_MAIN 0
#define HID_ITEM_TYPE_GLOBAL 1
#define HID_ITEM_TYPE_LOCAL 2
#define HID_ITEM_TYPE_RESERVED 3
/*
* HID report descriptor main item tags
*/
#define HID_MAIN_ITEM_TAG_INPUT 8
#define HID_MAIN_ITEM_TAG_OUTPUT 9
#define HID_MAIN_ITEM_TAG_FEATURE 11
#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10
#define HID_MAIN_ITEM_TAG_END_COLLECTION 12
/*
* HID report descriptor main item contents
*/
#define HID_MAIN_ITEM_CONSTANT 0x001
#define HID_MAIN_ITEM_VARIABLE 0x002
#define HID_MAIN_ITEM_RELATIVE 0x004
#define HID_MAIN_ITEM_WRAP 0x008
#define HID_MAIN_ITEM_NONLINEAR 0x010
#define HID_MAIN_ITEM_NO_PREFERRED 0x020
#define HID_MAIN_ITEM_NULL_STATE 0x040
#define HID_MAIN_ITEM_VOLATILE 0x080
#define HID_MAIN_ITEM_BUFFERED_BYTE 0x100
/*
* HID report descriptor collection item types
*/
#define HID_COLLECTION_PHYSICAL 0
#define HID_COLLECTION_APPLICATION 1
#define HID_COLLECTION_LOGICAL 2
/*
* HID report descriptor global item tags
*/
#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0
#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1
#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2
#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3
#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4
#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5
#define HID_GLOBAL_ITEM_TAG_UNIT 6
#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7
#define HID_GLOBAL_ITEM_TAG_REPORT_ID 8
#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9
#define HID_GLOBAL_ITEM_TAG_PUSH 10
#define HID_GLOBAL_ITEM_TAG_POP 11
/*
* HID report descriptor local item tags
*/
#define HID_LOCAL_ITEM_TAG_USAGE 0
#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1
#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2
#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3
#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4
#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5
#define HID_LOCAL_ITEM_TAG_STRING_INDEX 7
#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8
#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9
#define HID_LOCAL_ITEM_TAG_DELIMITER 10
/*
* HID usage tables
*/
#define HID_USAGE_PAGE 0xffff0000
#define HID_UP_GENDESK 0x00010000
#define HID_UP_KEYBOARD 0x00070000
#define HID_UP_LED 0x00080000
#define HID_UP_BUTTON 0x00090000
#define HID_UP_CONSUMER 0x000c0000
#define HID_UP_DIGITIZER 0x000d0000
#define HID_UP_PID 0x000f0000
#define HID_UP_HPVENDOR 0xff7f0000
#define HID_USAGE 0x0000ffff
#define HID_GD_POINTER 0x00010001
#define HID_GD_MOUSE 0x00010002
#define HID_GD_JOYSTICK 0x00010004
#define HID_GD_GAMEPAD 0x00010005
#define HID_GD_HATSWITCH 0x00010039
/*
* HID report types --- Ouch! HID spec says 1 2 3!
*/
#define HID_INPUT_REPORT 0
#define HID_OUTPUT_REPORT 1
#define HID_FEATURE_REPORT 2
/*
* HID device quirks.
*/
#define HID_QUIRK_INVERT 0x01
#define HID_QUIRK_NOTOUCH 0x02
/*
* This is the global enviroment of the parser. This information is
* persistent for main-items. The global enviroment can be saved and
* restored with PUSH/POP statements.
*/
struct hid_global {
unsigned usage_page;
__s32 logical_minimum;
__s32 logical_maximum;
__s32 physical_minimum;
__s32 physical_maximum;
unsigned unit_exponent;
unsigned unit;
unsigned report_id;
unsigned report_size;
unsigned report_count;
};
/*
* This is the local enviroment. It is resistent up the next main-item.
*/
#define HID_MAX_DESCRIPTOR_SIZE 4096
#define HID_MAX_USAGES 1024
#define HID_MAX_APPLICATIONS 16
struct hid_local {
unsigned usage[HID_MAX_USAGES]; /* usage array */
unsigned usage_index;
unsigned usage_minimum;
unsigned delimiter_depth;
unsigned delimiter_branch;
};
/*
* This is the collection stack. We climb up the stack to determine
* application and function of each field.
*/
struct hid_collection {
unsigned type;
unsigned usage;
};
struct hid_usage {
unsigned hid; /* hid usage code */
__u16 code; /* input driver code */
__u8 type; /* input driver type */
__s8 hat_min; /* hat switch fun */
__s8 hat_max; /* ditto */
};
struct hid_field {
unsigned physical; /* physical usage for this field */
unsigned logical; /* logical usage for this field */
unsigned application; /* application usage for this field */
struct hid_usage *usage; /* usage table for this function */
unsigned maxusage; /* maximum usage index */
unsigned flags; /* main-item flags (i.e. volatile,array,constant) */
unsigned report_offset; /* bit offset in the report */
unsigned report_size; /* size of this field in the report */
unsigned report_count; /* number of this field in the report */
unsigned report_type; /* (input,output,feature) */
__s32 *value; /* last known value(s) */
__s32 logical_minimum;
__s32 logical_maximum;
__s32 physical_minimum;
__s32 physical_maximum;
unsigned unit_exponent;
unsigned unit;
struct hid_report *report; /* associated report */
};
#define HID_MAX_FIELDS 64
struct hid_report {
struct list_head list;
unsigned id; /* id of this report */
unsigned type; /* report type */
struct hid_field *field[HID_MAX_FIELDS]; /* fields of the report */
unsigned maxfield; /* maximum valid field index */
unsigned size; /* size of the report (bits) */
struct hid_device *device; /* associated device */
};
struct hid_report_enum {
unsigned numbered;
struct list_head report_list;
struct hid_report *report_id_hash[256];
};
#define HID_REPORT_TYPES 3
#define HID_BUFFER_SIZE 32
#define HID_CONTROL_FIFO_SIZE 64
struct hid_control_fifo {
unsigned char dir;
struct hid_report *report;
};
#define HID_CLAIMED_INPUT 1
#define HID_CLAIMED_HIDDEV 2
struct hid_device { /* device report descriptor */
__u8 *rdesc;
unsigned rsize;
unsigned application[HID_MAX_APPLICATIONS]; /* List of HID applications */
unsigned maxapplication; /* Number of applications */
unsigned version; /* HID version */
unsigned country; /* HID country */
struct hid_report_enum report_enum[HID_REPORT_TYPES];
struct usb_device *dev; /* USB device */
int ifnum; /* USB interface number */
struct urb urb; /* USB URB structure */
char buffer[HID_BUFFER_SIZE]; /* Rx buffer */
struct urb urbctrl; /* Control URB */
struct usb_ctrlrequest dr; /* Control devrquest struct */
struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE]; /* Control fifo */
unsigned char ctrlhead, ctrltail; /* Control fifo head & tail */
char ctrlbuf[HID_BUFFER_SIZE]; /* Control buffer */
unsigned claimed; /* Claimed by hidinput, hiddev? */
unsigned quirks; /* Various quirks the device can pull on us */
struct input_dev input; /* The input structure */
void *hiddev; /* The hiddev structure */
int minor; /* Hiddev minor number */
wait_queue_head_t wait; /* For sleeping */
int open; /* is the device open by anyone? */
char name[128]; /* Device name */
char phys[64]; /* Device physical location */
char uniq[64]; /* Device unique identifier (serial #) */
};
#define HID_GLOBAL_STACK_SIZE 4
#define HID_COLLECTION_STACK_SIZE 4
struct hid_parser {
struct hid_global global;
struct hid_global global_stack[HID_GLOBAL_STACK_SIZE];
unsigned global_stack_ptr;
struct hid_local local;
struct hid_collection collection_stack[HID_COLLECTION_STACK_SIZE];
unsigned collection_stack_ptr;
struct hid_device *device;
};
struct hid_class_descriptor {
__u8 bDescriptorType;
__u16 wDescriptorLength;
} __attribute__ ((packed));
struct hid_descriptor {
__u8 bLength;
__u8 bDescriptorType;
__u16 bcdHID;
__u8 bCountryCode;
__u8 bNumDescriptors;
struct hid_class_descriptor desc[1];
} __attribute__ ((packed));
void hidinput_hid_event(struct hid_device *, struct hid_field *, struct hid_usage *, __s32);
int hidinput_connect(struct hid_device *);
void hidinput_disconnect(struct hid_device *);
#ifdef DEBUG
#include "hid-debug.h"
#else
#define hid_dump_input(a,b) do { } while (0)
#define hid_dump_device(c) do { } while (0)
#endif
#endif
/* Applications from HID Usage Tables 4/8/99 Version 1.1 */
/* We ignore a few input applications that are not widely used */
#define IS_INPUT_APPLICATION(a) (((a >= 0x00010000) && (a <= 0x00010008)) || ( a == 0x00010080) || ( a == 0x000c0001))
int hid_open(struct hid_device *);
void hid_close(struct hid_device *);
int hid_find_field(struct hid_device *, unsigned int, unsigned int, struct hid_field **);
int hid_set_field(struct hid_field *, unsigned, __s32);
void hid_submit_report(struct hid_device *, struct hid_report *, unsigned char dir);
void hid_init_reports(struct hid_device *hid);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:57:13
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/usb
In directory usw-pr-cvs1:/tmp/cvs-serv17144
Added Files:
Tag: 1.19
hid-input.c
Log Message:
Moved.
--- NEW FILE: hid-input.c ---
/*
* $Id: hid-input.c,v 1.19 2002/01/22 20:57:11 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* USB HID to Linux Input mapping
*/
/*
* 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/input.h>
#include <linux/usb.h>
#include "hid.h"
#define unk KEY_UNKNOWN
static unsigned char hid_keyboard[256] = {
0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
27, 43, 84, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
72, 73, 82, 83, 86,127,116,117, 85, 89, 90, 91, 92, 93, 94, 95,
120,121,122,123,134,138,130,132,128,129,131,137,133,135,136,113,
115,114,unk,unk,unk,124,unk,181,182,183,184,185,186,187,188,189,
190,191,192,193,194,195,196,197,198,unk,unk,unk,unk,unk,unk,unk,
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,unk,
29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
150,158,159,128,136,177,178,176,142,152,173,140,unk,unk,unk,unk
};
static struct {
__s32 x;
__s32 y;
} hid_hat_to_axis[] = {{ 0, 0}, { 0,-1}, { 1,-1}, { 1, 0}, { 1, 1}, { 0, 1}, {-1, 1}, {-1, 0}, {-1,-1}};
static void hidinput_configure_usage(struct hid_device *device, struct hid_field *field, struct hid_usage *usage)
{
struct input_dev *input = &device->input;
int max;
int is_abs = 0;
unsigned long *bit;
switch (usage->hid & HID_USAGE_PAGE) {
case HID_UP_KEYBOARD:
set_bit(EV_REP, input->evbit);
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
if ((usage->hid & HID_USAGE) < 256) {
if (!(usage->code = hid_keyboard[usage->hid & HID_USAGE]))
return;
clear_bit(usage->code, bit);
} else
usage->code = KEY_UNKNOWN;
break;
case HID_UP_BUTTON:
usage->code = ((usage->hid - 1) & 0xf) + 0x100;
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
switch (field->application) {
case HID_GD_GAMEPAD: usage->code += 0x10;
case HID_GD_JOYSTICK: usage->code += 0x10;
case HID_GD_MOUSE: usage->code += 0x10; break;
default:
if (field->physical == HID_GD_POINTER)
usage->code += 0x10;
break;
}
break;
case HID_UP_GENDESK:
if ((usage->hid & 0xf0) == 0x80) { /* SystemControl */
switch (usage->hid & 0xf) {
case 0x1: usage->code = KEY_POWER; break;
case 0x2: usage->code = KEY_SLEEP; break;
case 0x3: usage->code = KEY_WAKEUP; break;
default: usage->code = KEY_UNKNOWN; break;
}
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
break;
}
usage->code = usage->hid & 0xf;
if (field->report_size == 1) {
usage->code = BTN_MISC;
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
break;
}
if (field->flags & HID_MAIN_ITEM_RELATIVE) {
usage->type = EV_REL; bit = input->relbit; max = REL_MAX;
break;
}
usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
if (usage->hid == HID_GD_HATSWITCH) {
usage->code = ABS_HAT0X;
usage->hat_min = field->logical_minimum;
usage->hat_max = field->logical_maximum;
}
break;
case HID_UP_LED:
usage->code = (usage->hid - 1) & 0xf;
usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
break;
case HID_UP_DIGITIZER:
switch (usage->hid & 0xff) {
case 0x30: /* TipPressure */
if (!test_bit(BTN_TOUCH, input->keybit)) {
device->quirks |= HID_QUIRK_NOTOUCH;
set_bit(EV_KEY, input->evbit);
set_bit(BTN_TOUCH, input->keybit);
}
usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
usage->code = ABS_PRESSURE;
clear_bit(usage->code, bit);
break;
case 0x32: /* InRange */
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
switch (field->physical & 0xff) {
case 0x21: usage->code = BTN_TOOL_MOUSE; break;
case 0x22: usage->code = BTN_TOOL_FINGER; break;
default: usage->code = BTN_TOOL_PEN; break;
}
break;
case 0x3c: /* Invert */
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
usage->code = BTN_TOOL_RUBBER;
clear_bit(usage->code, bit);
break;
case 0x33: /* Touch */
case 0x42: /* TipSwitch */
case 0x43: /* TipSwitch2 */
device->quirks &= ~HID_QUIRK_NOTOUCH;
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
usage->code = BTN_TOUCH;
clear_bit(usage->code, bit);
break;
case 0x44: /* BarrelSwitch */
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
usage->code = BTN_STYLUS;
clear_bit(usage->code, bit);
break;
default: goto unknown;
}
break;
case HID_UP_CONSUMER: /* USB HUT v1.1, pages 56-62 */
set_bit(EV_REP, input->evbit);
switch (usage->hid & HID_USAGE) {
case 0x000: usage->code = 0; break;
case 0x034: usage->code = KEY_SLEEP; break;
case 0x036: usage->code = BTN_MISC; break;
case 0x08a: usage->code = KEY_WWW; break;
case 0x095: usage->code = KEY_HELP; break;
case 0x0b0: usage->code = KEY_PLAY; break;
case 0x0b1: usage->code = KEY_PAUSE; break;
case 0x0b2: usage->code = KEY_RECORD; break;
case 0x0b3: usage->code = KEY_FASTFORWARD; break;
case 0x0b4: usage->code = KEY_REWIND; break;
case 0x0b5: usage->code = KEY_NEXTSONG; break;
case 0x0b6: usage->code = KEY_PREVIOUSSONG; break;
case 0x0b7: usage->code = KEY_STOPCD; break;
case 0x0b8: usage->code = KEY_EJECTCD; break;
case 0x0cd: usage->code = KEY_PLAYPAUSE; break;
case 0x0e0: is_abs = 1;
usage->code = ABS_VOLUME;
break;
case 0x0e2: usage->code = KEY_MUTE; break;
case 0x0e5: usage->code = KEY_BASSBOOST; break;
case 0x0e9: usage->code = KEY_VOLUMEUP; break;
case 0x0ea: usage->code = KEY_VOLUMEDOWN; break;
case 0x183: usage->code = KEY_CONFIG; break;
case 0x18a: usage->code = KEY_MAIL; break;
case 0x192: usage->code = KEY_CALC; break;
case 0x194: usage->code = KEY_FILE; break;
case 0x21a: usage->code = KEY_UNDO; break;
case 0x21b: usage->code = KEY_COPY; break;
case 0x21c: usage->code = KEY_CUT; break;
case 0x21d: usage->code = KEY_PASTE; break;
case 0x221: usage->code = KEY_FIND; break;
case 0x223: usage->code = KEY_HOMEPAGE; break;
case 0x224: usage->code = KEY_BACK; break;
case 0x225: usage->code = KEY_FORWARD; break;
case 0x226: usage->code = KEY_STOP; break;
case 0x227: usage->code = KEY_REFRESH; break;
case 0x22a: usage->code = KEY_BOOKMARKS; break;
default: usage->code = KEY_UNKNOWN; break;
}
if (is_abs) {
usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
} else {
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
}
break;
case HID_UP_HPVENDOR: /* Reported on a Dutch layout HP5308 */
set_bit(EV_REP, input->evbit);
switch (usage->hid & HID_USAGE) {
case 0x021: usage->code = KEY_PRINT; break;
case 0x070: usage->code = KEY_HP; break;
case 0x071: usage->code = KEY_CAMERA; break;
case 0x072: usage->code = KEY_SOUND; break;
case 0x073: usage->code = KEY_QUESTION; break;
case 0x080: usage->code = KEY_EMAIL; break;
case 0x081: usage->code = KEY_CHAT; break;
case 0x082: usage->code = KEY_SEARCH; break;
case 0x083: usage->code = KEY_CONNECT; break;
case 0x084: usage->code = KEY_FINANCE; break;
case 0x085: usage->code = KEY_SPORT; break;
case 0x086: usage->code = KEY_SHOP; break;
default: usage->code = KEY_UNKNOWN; break;
}
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
break;
default:
unknown:
if (field->report_size == 1) {
if (field->report->type == HID_OUTPUT_REPORT) {
usage->code = LED_MISC;
usage->type = EV_LED; bit = input->ledbit; max = LED_MAX;
break;
}
usage->code = BTN_MISC;
usage->type = EV_KEY; bit = input->keybit; max = KEY_MAX;
break;
}
if (field->flags & HID_MAIN_ITEM_RELATIVE) {
usage->code = REL_MISC;
usage->type = EV_REL; bit = input->relbit; max = REL_MAX;
break;
}
usage->code = ABS_MISC;
usage->type = EV_ABS; bit = input->absbit; max = ABS_MAX;
break;
}
set_bit(usage->type, input->evbit);
while (usage->code <= max && test_and_set_bit(usage->code, bit)) {
usage->code = find_next_zero_bit(bit, max + 1, usage->code);
}
if (usage->code > max) return;
if (usage->type == EV_ABS) {
int a = field->logical_minimum;
int b = field->logical_maximum;
input->absmin[usage->code] = a;
input->absmax[usage->code] = b;
input->absfuzz[usage->code] = (b - a) >> 8;
input->absflat[usage->code] = (b - a) >> 4;
}
if (usage->hat_min != usage->hat_max) {
int i;
for (i = usage->code; i < usage->code + 2 && i <= max; i++) {
input->absmax[i] = 1;
input->absmin[i] = -1;
input->absfuzz[i] = 0;
input->absflat[i] = 0;
}
set_bit(usage->code + 1, input->absbit);
}
}
void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct hid_usage *usage, __s32 value)
{
struct input_dev *input = &hid->input;
int *quirks = &hid->quirks;
if (usage->hat_min != usage->hat_max) {
value = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
if (value < 0 || value > 8) value = 0;
input_event(input, usage->type, usage->code , hid_hat_to_axis[value].x);
input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[value].y);
return;
}
if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
*quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
return;
}
if (usage->hid == (HID_UP_DIGITIZER | 0x0032)) { /* InRange */
if (value) {
input_event(input, usage->type, (*quirks & HID_QUIRK_INVERT) ? BTN_TOOL_RUBBER : usage->code, 1);
return;
}
input_event(input, usage->type, usage->code, 0);
input_event(input, usage->type, BTN_TOOL_RUBBER, 0);
return;
}
if (usage->hid == (HID_UP_DIGITIZER | 0x0030) && (*quirks & HID_QUIRK_NOTOUCH)) { /* Pressure */
int a = field->logical_minimum;
int b = field->logical_maximum;
input_event(input, EV_KEY, BTN_TOUCH, value > a + ((b - a) >> 3));
}
if((usage->type == EV_KEY) && (usage->code == 0)) /* Key 0 is "unassigned", not KEY_UKNOWN */
return;
input_event(input, usage->type, usage->code, value);
if ((field->flags & HID_MAIN_ITEM_RELATIVE) && (usage->type == EV_KEY))
input_event(input, usage->type, usage->code, 0);
}
static int hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
struct hid_device *hid = dev->private;
struct hid_field *field = NULL;
int offset;
if ((offset = hid_find_field(hid, type, code, &field)) == -1) {
warn("event field not found");
return -1;
}
hid_set_field(field, offset, value);
hid_submit_report(hid, field->report, USB_DIR_OUT);
return 0;
}
static int hidinput_open(struct input_dev *dev)
{
struct hid_device *hid = dev->private;
return hid_open(hid);
}
static void hidinput_close(struct input_dev *dev)
{
struct hid_device *hid = dev->private;
hid_close(hid);
}
/*
* Register the input device; print a message.
* Configure the input layer interface
* Read all reports and initalize the absoulte field values.
*/
int hidinput_connect(struct hid_device *hid)
{
struct usb_device *dev = hid->dev;
struct hid_report_enum *report_enum;
struct hid_report *report;
struct list_head *list;
int i, j, k;
for (i = 0; i < hid->maxapplication; i++)
if (IS_INPUT_APPLICATION(hid->application[i]))
break;
if (i == hid->maxapplication)
return -1;
hid->input.private = hid;
hid->input.event = hidinput_input_event;
hid->input.open = hidinput_open;
hid->input.close = hidinput_close;
hid->input.name = hid->name;
hid->input.phys = hid->phys;
hid->input.uniq = hid->uniq;
hid->input.idbus = BUS_USB;
hid->input.idvendor = dev->descriptor.idVendor;
hid->input.idproduct = dev->descriptor.idProduct;
hid->input.idversion = dev->descriptor.bcdDevice;
for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
report_enum = hid->report_enum + k;
list = report_enum->report_list.next;
while (list != &report_enum->report_list) {
report = (struct hid_report *) list;
for (i = 0; i < report->maxfield; i++)
for (j = 0; j < report->field[i]->maxusage; j++)
hidinput_configure_usage(hid, report->field[i], report->field[i]->usage + j);
list = list->next;
}
}
input_register_device(&hid->input);
return 0;
}
void hidinput_disconnect(struct hid_device *hid)
{
input_unregister_device(&hid->input);
}
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:56:59
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/usb
In directory usw-pr-cvs1:/tmp/cvs-serv17041
Added Files:
Tag: 1.9
hid-debug.h
Log Message:
Moved.
--- NEW FILE: hid-debug.h ---
/*
* $Id: hid-debug.h,v 1.9 2002/01/22 20:56:57 vojtech Exp $
*
* (c) 1999 Andreas Gal <ga...@cs...>
* (c) 2000-2001 Vojtech Pavlik <vo...@uc...>
*
* Some debug stuff for the HID parser.
*/
/*
* 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
struct hid_usage_entry {
unsigned page;
unsigned usage;
char *description;
};
static struct hid_usage_entry hid_usage_table[] = {
{ 1, 0, "GenericDesktop" },
{0, 0x01, "Pointer"},
{0, 0x02, "Mouse"},
{0, 0x04, "Joystick"},
{0, 0x05, "GamePad"},
{0, 0x06, "Keyboard"},
{0, 0x07, "Keypad"},
{0, 0x08, "MultiAxis"},
{0, 0x30, "X"},
{0, 0x31, "Y"},
{0, 0x32, "Z"},
{0, 0x33, "Rx"},
{0, 0x34, "Ry"},
{0, 0x35, "Rz"},
{0, 0x36, "Slider"},
{0, 0x37, "Dial"},
{0, 0x38, "Wheel"},
{0, 0x39, "HatSwitch"},
{0, 0x3a, "CountedBuffer"},
{0, 0x3b, "ByteCount"},
{0, 0x3c, "MotionWakeup"},
{0, 0x3d, "Start"},
{0, 0x3e, "Select"},
{0, 0x40, "Vx"},
{0, 0x41, "Vy"},
{0, 0x42, "Vz"},
{0, 0x43, "Vbrx"},
{0, 0x44, "Vbry"},
{0, 0x45, "Vbrz"},
{0, 0x46, "Vno"},
{0, 0x80, "SystemControl"},
{0, 0x81, "SystemPowerDown"},
{0, 0x82, "SystemSleep"},
{0, 0x83, "SystemWakeUp"},
{0, 0x84, "SystemContextMenu"},
{0, 0x85, "SystemMainMenu"},
{0, 0x86, "SystemAppMenu"},
{0, 0x87, "SystemMenuHelp"},
{0, 0x88, "SystemMenuExit"},
{0, 0x89, "SystemMenuSelect"},
{0, 0x8a, "SystemMenuRight"},
{0, 0x8b, "SystemMenuLeft"},
{0, 0x8c, "SystemMenuUp"},
{0, 0x8d, "SystemMenuDown"},
{0, 0x90, "D-padUp"},
{0, 0x91, "D-padDown"},
{0, 0x92, "D-padRight"},
{0, 0x93, "D-padLeft"},
{ 7, 0, "Keyboard" },
{ 8, 0, "LED" },
{ 9, 0, "Button" },
{ 12, 0, "Hotkey" },
{ 13, 0, "Digitizers" },
{0, 0x01, "Digitizer"},
{0, 0x02, "Pen"},
{0, 0x03, "LightPen"},
{0, 0x04, "TouchScreen"},
{0, 0x05, "TouchPad"},
{0, 0x20, "Stylus"},
{0, 0x21, "Puck"},
{0, 0x22, "Finger"},
{0, 0x30, "TipPressure"},
{0, 0x31, "BarrelPressure"},
{0, 0x32, "InRange"},
{0, 0x33, "Touch"},
{0, 0x34, "UnTouch"},
{0, 0x35, "Tap"},
{0, 0x39, "TabletFunctionKey"},
{0, 0x3a, "ProgramChangeKey"},
{0, 0x3c, "Invert"},
{0, 0x42, "TipSwitch"},
{0, 0x43, "SecondaryTipSwitch"},
{0, 0x44, "BarrelSwitch"},
{0, 0x45, "Eraser"},
{0, 0x46, "TabletPick"},
{ 15, 0, "PhysicalInterfaceDevice" },
{ 0, 0, NULL }
};
static void resolv_usage_page(unsigned page) {
struct hid_usage_entry *p;
for (p = hid_usage_table; p->description; p++)
if (p->page == page) {
printk("%s", p->description);
return;
}
printk("%04x", page);
}
static void resolv_usage(unsigned usage) {
struct hid_usage_entry *p;
resolv_usage_page(usage >> 16);
printk(".");
for (p = hid_usage_table; p->description; p++)
if (p->page == (usage >> 16)) {
for(++p; p->description && p->page == 0; p++)
if (p->usage == (usage & 0xffff)) {
printk("%s", p->description);
return;
}
break;
}
printk("%04x", usage & 0xffff);
}
__inline__ static void tab(int n) {
while (n--) printk(" ");
}
static void hid_dump_field(struct hid_field *field, int n) {
int j;
if (field->physical) {
tab(n);
printk("Physical(");
resolv_usage(field->physical); printk(")\n");
}
if (field->logical) {
tab(n);
printk("Logical(");
resolv_usage(field->logical); printk(")\n");
}
tab(n); printk("Usage(%d)\n", field->maxusage);
for (j = 0; j < field->maxusage; j++) {
tab(n+2);resolv_usage(field->usage[j].hid); printk("\n");
}
if (field->logical_minimum != field->logical_maximum) {
tab(n); printk("Logical Minimum(%d)\n", field->logical_minimum);
tab(n); printk("Logical Maximum(%d)\n", field->logical_maximum);
}
if (field->physical_minimum != field->physical_maximum) {
tab(n); printk("Physical Minimum(%d)\n", field->physical_minimum);
tab(n); printk("Physical Maximum(%d)\n", field->physical_maximum);
}
if (field->unit_exponent) {
tab(n); printk("Unit Exponent(%d)\n", field->unit_exponent);
}
if (field->unit) {
tab(n); printk("Unit(%u)\n", field->unit);
}
tab(n); printk("Report Size(%u)\n", field->report_size);
tab(n); printk("Report Count(%u)\n", field->report_count);
tab(n); printk("Report Offset(%u)\n", field->report_offset);
tab(n); printk("Flags( ");
j = field->flags;
printk("%s", HID_MAIN_ITEM_CONSTANT & j ? "Constant " : "");
printk("%s", HID_MAIN_ITEM_VARIABLE & j ? "Variable " : "Array ");
printk("%s", HID_MAIN_ITEM_RELATIVE & j ? "Relative " : "Absolute ");
printk("%s", HID_MAIN_ITEM_WRAP & j ? "Wrap " : "");
printk("%s", HID_MAIN_ITEM_NONLINEAR & j ? "NonLinear " : "");
printk("%s", HID_MAIN_ITEM_NO_PREFERRED & j ? "NoPrefferedState " : "");
printk("%s", HID_MAIN_ITEM_NULL_STATE & j ? "NullState " : "");
printk("%s", HID_MAIN_ITEM_VOLATILE & j ? "Volatile " : "");
printk("%s", HID_MAIN_ITEM_BUFFERED_BYTE & j ? "BufferedByte " : "");
printk(")\n");
}
static void hid_dump_device(struct hid_device *device) {
struct hid_report_enum *report_enum;
struct hid_report *report;
struct list_head *list;
unsigned i,k;
static char *table[] = {"INPUT", "OUTPUT", "FEATURE"};
for (i = 0; i < device->maxapplication; i++) {
printk("Application(");
resolv_usage(device->application[i]);
printk(")\n");
}
for (i = 0; i < HID_REPORT_TYPES; i++) {
report_enum = device->report_enum + i;
list = report_enum->report_list.next;
while (list != &report_enum->report_list) {
report = (struct hid_report *) list;
tab(2);
printk("%s", table[i]);
if (report->id)
printk("(%d)", report->id);
printk("[%s]", table[report->type]);
printk("\n");
for (k = 0; k < report->maxfield; k++) {
tab(4);
printk("Field(%d)\n", k);
hid_dump_field(report->field[k], 6);
}
list = list->next;
}
}
}
static void hid_dump_input(struct hid_usage *usage, __s32 value) {
printk("hid-debug: input ");
resolv_usage(usage->hid);
printk(" = %d\n", value);
}
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:56:45
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/usb
In directory usw-pr-cvs1:/tmp/cvs-serv16879
Added Files:
Tag: 1.37
hid-core.c
Log Message:
Moved.
--- NEW FILE: hid-core.c ---
/*
* $Id: hid-core.c,v 1.37 2002/01/22 20:56:42 vojtech Exp $
*
* Copyright (c) 1999 Andreas Gal
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* USB HID support 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.
[...1297 lines suppressed...]
usb_register(&hid_driver);
info(DRIVER_VERSION ":" DRIVER_DESC);
return 0;
}
static void __exit hid_exit(void)
{
#ifdef CONFIG_USB_HIDDEV
hiddev_exit();
#endif
usb_deregister(&hid_driver);
}
module_init(hid_init);
module_exit(hid_exit);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE(DRIVER_LICENSE);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:49:20
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/mouse
In directory usw-pr-cvs1:/tmp/cvs-serv14518
Added Files:
Tag: 1.16
sermouse.c
Log Message:
Moved.
--- NEW FILE: sermouse.c ---
/*
* $Id: sermouse.c,v 1.16 2002/01/22 20:49:17 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* Serial mouse 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/config.h>
#include <linux/serio.h>
#include <linux/init.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>");
MODULE_DESCRIPTION("Serial mouse driver");
MODULE_LICENSE("GPL");
static char *sermouse_protocols[] = { "None", "Mouse Systems Mouse", "Sun Mouse", "Microsoft Mouse",
"Logitech M+ Mouse", "Microsoft MZ Mouse", "Logitech MZ+ Mouse",
"Logitech MZ++ Mouse"};
struct sermouse {
struct input_dev dev;
signed char buf[8];
unsigned char count;
unsigned char type;
unsigned long last;
char phys[32];
};
/*
* sermouse_process_msc() analyzes the incoming MSC/Sun bytestream and
* applies some prediction to the data, resulting in 96 updates per
* second, which is as good as a PS/2 or USB mouse.
*/
static void sermouse_process_msc(struct sermouse *sermouse, signed char data)
{
struct input_dev *dev = &sermouse->dev;
signed char *buf = sermouse->buf;
switch (sermouse->count) {
case 0:
if ((data & 0xf8) != 0x80) return;
input_report_key(dev, BTN_LEFT, !(data & 4));
input_report_key(dev, BTN_RIGHT, !(data & 1));
input_report_key(dev, BTN_MIDDLE, !(data & 2));
break;
case 1:
case 3:
input_report_rel(dev, REL_X, data / 2);
input_report_rel(dev, REL_Y, -buf[1]);
buf[0] = data - data / 2;
break;
case 2:
case 4:
input_report_rel(dev, REL_X, buf[0]);
input_report_rel(dev, REL_Y, buf[1] - data);
buf[1] = data / 2;
break;
}
if (++sermouse->count == (5 - ((sermouse->type == SERIO_SUN) << 1)))
sermouse->count = 0;
}
/*
* sermouse_process_ms() anlyzes the incoming MS(Z/+/++) bytestream and
* generates events. With prediction it gets 80 updates/sec, assuming
* standard 3-byte packets and 1200 bps.
*/
static void sermouse_process_ms(struct sermouse *sermouse, signed char data)
{
struct input_dev *dev = &sermouse->dev;
signed char *buf = sermouse->buf;
if (data & 0x40) sermouse->count = 0;
switch (sermouse->count) {
case 0:
buf[1] = data;
input_report_key(dev, BTN_LEFT, (data >> 5) & 1);
input_report_key(dev, BTN_RIGHT, (data >> 4) & 1);
break;
case 1:
buf[2] = data;
data = (signed char) (((buf[1] << 6) & 0xc0) | (data & 0x3f));
input_report_rel(dev, REL_X, data / 2);
input_report_rel(dev, REL_Y, buf[4]);
buf[3] = data - data / 2;
break;
case 2:
/* Guessing the state of the middle button on 3-button MS-protocol mice - ugly. */
if ((sermouse->type == SERIO_MS) && !data && !buf[2] && !((buf[0] & 0xf0) ^ buf[1]))
input_report_key(dev, BTN_MIDDLE, !test_bit(BTN_MIDDLE, dev->key));
buf[0] = buf[1];
data = (signed char) (((buf[1] << 4) & 0xc0) | (data & 0x3f));
input_report_rel(dev, REL_X, buf[3]);
input_report_rel(dev, REL_Y, data - buf[4]);
buf[4] = data / 2;
break;
case 3:
switch (sermouse->type) {
case SERIO_MS:
sermouse->type = SERIO_MP;
case SERIO_MP:
if ((data >> 2) & 3) break; /* M++ Wireless Extension packet. */
input_report_key(dev, BTN_MIDDLE, (data >> 5) & 1);
input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
break;
case SERIO_MZP:
case SERIO_MZPP:
input_report_key(dev, BTN_SIDE, (data >> 5) & 1);
case SERIO_MZ:
input_report_key(dev, BTN_MIDDLE, (data >> 4) & 1);
input_report_rel(dev, REL_WHEEL, (data & 7) - (data & 8));
break;
}
break;
case 4:
case 6: /* MZ++ packet type. We can get these bytes for M++ too but we ignore them later. */
buf[1] = (data >> 2) & 0x0f;
break;
case 5:
case 7: /* Ignore anything besides MZ++ */
if (sermouse->type != SERIO_MZPP) break;
switch (buf[1]) {
case 1: /* Extra mouse info */
input_report_key(dev, BTN_SIDE, (data >> 4) & 1);
input_report_key(dev, BTN_EXTRA, (data >> 5) & 1);
input_report_rel(dev, data & 0x80 ? REL_HWHEEL : REL_WHEEL, (data & 7) - (data & 8));
break;
default: /* We don't decode anything else yet. */
printk(KERN_WARNING
"sermouse.c: Received MZ++ packet %x, don't know how to handle.\n", buf[1]);
break;
}
break;
}
sermouse->count++;
}
/*
* sermouse_interrupt() handles incoming characters, either gathering them into
* packets or passing them to the command routine as command output.
*/
static void sermouse_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
{
struct sermouse *sermouse = serio->private;
if (jiffies - sermouse->last > 2) sermouse->count = 0;
sermouse->last = jiffies;
if (sermouse->type > SERIO_SUN)
sermouse_process_ms(sermouse, data);
else
sermouse_process_msc(sermouse, data);
}
/*
* sermouse_disconnect() cleans up after we don't want talk
* to the mouse anymore.
*/
static void sermouse_disconnect(struct serio *serio)
{
struct sermouse *sermouse = serio->private;
input_unregister_device(&sermouse->dev);
serio_close(serio);
kfree(sermouse);
}
/*
* sermouse_connect() is a callback form the serio module when
* an unhandled serio port is found.
*/
static void sermouse_connect(struct serio *serio, struct serio_dev *dev)
{
struct sermouse *sermouse;
unsigned char c;
if ((serio->type & SERIO_TYPE) != SERIO_RS232)
return;
if (!(serio->type & SERIO_PROTO) || ((serio->type & SERIO_PROTO) > SERIO_MZPP))
return;
if (!(sermouse = kmalloc(sizeof(struct sermouse), GFP_KERNEL)))
return;
memset(sermouse, 0, sizeof(struct sermouse));
sermouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
sermouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT);
sermouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
sermouse->dev.private = sermouse;
serio->private = sermouse;
sermouse->type = serio->type & SERIO_PROTO;
c = (serio->type & SERIO_EXTRA) >> 16;
if (c & 0x01) set_bit(BTN_MIDDLE, &sermouse->dev.keybit);
if (c & 0x02) set_bit(BTN_SIDE, &sermouse->dev.keybit);
if (c & 0x04) set_bit(BTN_EXTRA, &sermouse->dev.keybit);
if (c & 0x10) set_bit(REL_WHEEL, &sermouse->dev.relbit);
if (c & 0x20) set_bit(REL_HWHEEL, &sermouse->dev.relbit);
sprintf(sermouse->phys, "%s/input0", serio->phys);
sermouse->dev.name = sermouse_protocols[sermouse->type];
sermouse->dev.phys = sermouse->phys;
sermouse->dev.idbus = BUS_RS232;
sermouse->dev.idvendor = sermouse->type;
sermouse->dev.idproduct = c;
sermouse->dev.idversion = 0x0100;
if (serio_open(serio, dev)) {
kfree(sermouse);
return;
}
input_register_device(&sermouse->dev);
printk(KERN_INFO "input: %s on %s\n", sermouse_protocols[sermouse->type], serio->phys);
}
static struct serio_dev sermouse_dev = {
interrupt: sermouse_interrupt,
connect: sermouse_connect,
disconnect: sermouse_disconnect
};
int __init sermouse_init(void)
{
serio_register_device(&sermouse_dev);
return 0;
}
void __exit sermouse_exit(void)
{
serio_unregister_device(&sermouse_dev);
}
module_init(sermouse_init);
module_exit(sermouse_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:49:02
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/mouse
In directory usw-pr-cvs1:/tmp/cvs-serv14381
Added Files:
Tag: 1.12
rpcmouse.c
Log Message:
Moved.
--- NEW FILE: rpcmouse.c ---
/*
* $Id: rpcmouse.c,v 1.12 2002/01/22 20:48:59 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
* Russel King
*/
/*
* Acorn RiscPC mouse driver for Linux/ARM
*/
/*
* 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/ptrace.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/iomd.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>");
MODULE_DESCRIPTION("Acorn RiscPC mouse driver");
MODULE_LICENSE("GPL");
#define IOMD_MOUSEBTN 0x800C4000
static short rpcmouse_lastx, rpcmouse_lasty;
static struct input_dev rpcmouse_dev = {
evbit: { BIT(EV_KEY) | BIT(EV_REL) },
keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
relbit: { BIT(REL_X) | BIT(REL_Y) },
name: "Acorn RiscPC Mouse",
phys: "rpcmouse/input0",
idbus: BUS_ISA,
idvendor: 0x0005,
idproduct: 0x0001,
idversion: 0x0100,
};
static void rpcmouse_irq(int irq, void *dev_id, struct pt_regs *regs)
{
short x, y, dx, dy, b;
x = (short) inl(IOMD_MOUSEX);
y = (short) inl(IOMD_MOUSEY);
b = (short) inl(IOMD_MOUSEBTN);
dx = x - rpcmouse_lastx;
dy = y - rpcmouse_lasty;
rpcmouse_lastx = x;
rpcmouse_lasty = y;
input_report_rel(&rpcmouse_dev, REL_X, dx);
input_report_rel(&rpcmouse_dev, REL_Y, dy);
input_report_key(&amimouse_dev, BTN_LEFT, buttons & 0x10);
input_report_key(&amimouse_dev, BTN_MIDDLE, buttons & 0x20);
input_report_key(&amimouse_dev, BTN_RIGHT, buttons & 0x40);
}
static int __init rpcmouse_init(void)
{
rpcmouse_lastx = (short) inl(IOMD_MOUSEX);
rpcmouse_lasty = (short) inl(IOMD_MOUSEY);
if (request_irq(IRQ_VSYNCPULSE, rpcmouse_irq, SA_SHIRQ, "rpcmouse", NULL)) {
printk(KERN_ERR "rpcmouse: unable to allocate VSYNC interrupt\n");
return -1;
}
input_register_device(&rpcmouse_dev);
printk(KERN_INFO "input%d: Acorn RiscPC mouse irq %d", IRQ_VSYNCPULSE);
return 0;
}
static void __exit rpcmouse_exit(void)
{
input_unregister_device(&rpcmouse_dev);
free_irq(IRQ_VSYNCPULSE, NULL);
}
module_init(rpcmouse_init);
module_exit(rpcmouse_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:48:41
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/mouse
In directory usw-pr-cvs1:/tmp/cvs-serv14219
Added Files:
Tag: 1.15
psmouse.c
Log Message:
Moved.
--- NEW FILE: psmouse.c ---
/*
* $Id: psmouse.c,v 1.15 2002/01/22 20:48:38 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/delay.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>");
MODULE_DESCRIPTION("PS/2 mouse driver");
MODULE_LICENSE("GPL");
#define PSMOUSE_CMD_SETSCALE11 0x00e6
#define PSMOUSE_CMD_SETRES 0x10e8
#define PSMOUSE_CMD_GETINFO 0x03e9
#define PSMOUSE_CMD_SETSTREAM 0x00ea
#define PSMOUSE_CMD_POLL 0x03eb
#define PSMOUSE_CMD_GETID 0x01f2
#define PSMOUSE_CMD_SETRATE 0x10f3
#define PSMOUSE_CMD_ENABLE 0x00f4
#define PSMOUSE_CMD_RESET_DIS 0x00f6
#define PSMOUSE_RET_BAT 0xaa
#define PSMOUSE_RET_ACK 0xfa
#define PSMOUSE_RET_NAK 0xfe
struct psmouse {
struct input_dev dev;
struct serio *serio;
char *vendor;
char *name;
struct tq_struct tq;
unsigned char cmdbuf[8];
unsigned char packet[8];
unsigned char cmdcnt;
unsigned char pktcnt;
unsigned char type;
unsigned long last;
char acking;
char ack;
char error;
char devname[64];
char phys[32];
};
#define PSMOUSE_PS2 1
#define PSMOUSE_PS2PP 2
#define PSMOUSE_PS2TPP 3
#define PSMOUSE_GENPS 4
#define PSMOUSE_IMPS 5
#define PSMOUSE_IMEX 6
static char *psmouse_protocols[] = { "None", "PS/2", "PS2++", "PS2T++", "GenPS/2", "ImPS/2", "ImExPS/2" };
/*
* psmouse_process_packet() anlyzes the PS/2 mouse packet contents and
* reports relevant events to the input module.
*/
static void psmouse_process_packet(struct psmouse *psmouse)
{
struct input_dev *dev = &psmouse->dev;
unsigned char *packet = psmouse->packet;
/*
* The PS2++ protocol is a little bit complex
*/
if (psmouse->type == PSMOUSE_PS2PP || psmouse->type == PSMOUSE_PS2TPP) {
if ((packet[0] & 0x40) == 0x40 && (int) packet[1] - (int) ((packet[0] & 0x10) << 4) > 191 ) {
switch (((packet[1] >> 4) & 0x03) | ((packet[0] >> 2) & 0xc0)) {
case 1: /* Mouse extra info */
input_report_rel(dev, packet[2] & 0x80 ? REL_HWHEEL : REL_WHEEL,
(int) (packet[2] & 7) - (int) (packet[2] & 8));
input_report_key(dev, BTN_SIDE, (packet[2] >> 4) & 1);
input_report_key(dev, BTN_EXTRA, (packet[2] >> 5) & 1);
break;
case 3: /* TouchPad extra info */
input_report_rel(dev, packet[2] & 0x08 ? REL_HWHEEL : REL_WHEEL,
(int) ((packet[2] >> 4) & 7) - (int) ((packet[2] >> 4) & 8));
packet[0] = packet[2] | 0x08;
break;
default:
printk(KERN_WARNING "psmouse.c: Received PS2++ packet #%x, but don't know how to handle.\n",
((packet[1] >> 4) & 0x03) | ((packet[0] >> 2) & 0xc0));
}
packet[0] &= 0x0f;
packet[1] = 0;
packet[2] = 0;
}
}
/*
* Scroll wheel on IntelliMice, scroll buttons on NetMice
*/
if (psmouse->type == PSMOUSE_IMPS || psmouse->type == PSMOUSE_GENPS)
input_report_rel(dev, REL_WHEEL, (signed char) packet[3]);
/*
* Scroll wheel and buttons on IntelliMouse Explorer
*/
if (psmouse->type == PSMOUSE_IMEX) {
input_report_rel(dev, REL_WHEEL, (int) (packet[3] & 7) - (int) (packet[2] & 8));
input_report_key(dev, BTN_SIDE, (packet[3] >> 4) & 1);
input_report_key(dev, BTN_EXTRA, (packet[3] >> 5) & 1);
}
/*
* Extra buttons on Genius NewNet 3D
*/
if (psmouse->type == PSMOUSE_GENPS) {
input_report_key(dev, BTN_SIDE, (packet[0] >> 6) & 1);
input_report_key(dev, BTN_EXTRA, (packet[0] >> 7) & 1);
}
/*
* Generic PS/2 Mouse
*/
input_report_key(dev, BTN_LEFT, packet[0] & 1);
input_report_key(dev, BTN_MIDDLE, (packet[0] >> 2) & 1);
input_report_key(dev, BTN_RIGHT, (packet[0] >> 1) & 1);
input_report_rel(dev, REL_X, packet[1] ? (int) packet[1] - (int) ((packet[0] << 4) & 0x100) : 0);
input_report_rel(dev, REL_Y, packet[2] ? (int) ((packet[0] << 3) & 0x100) - (int) packet[2] : 0);
}
/*
* psmouse_interrupt() handles incoming characters, either gathering them into
* packets or passing them to the command routine as command output.
*/
static void psmouse_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
{
struct psmouse *psmouse = serio->private;
if (psmouse->acking) {
switch (data) {
case PSMOUSE_RET_ACK:
psmouse->ack = 1;
break;
case PSMOUSE_RET_NAK:
psmouse->ack = -1;
break;
}
psmouse->acking = 0;
return;
}
if (psmouse->cmdcnt) {
psmouse->cmdbuf[--psmouse->cmdcnt] = data;
return;
}
if (psmouse->pktcnt && jiffies - psmouse->last > 2) {
printk(KERN_WARNING "psmouse.c: Lost synchronization, throwing %d bytes away.\n", psmouse->pktcnt);
psmouse->pktcnt = 0;
}
psmouse->last = jiffies;
psmouse->packet[psmouse->pktcnt++] = data;
if (psmouse->pktcnt == 3 + (psmouse->type >= PSMOUSE_GENPS)) {
if ((psmouse->packet[0] & 0x08) == 0x08) psmouse_process_packet(psmouse);
psmouse->pktcnt = 0;
return;
}
if (psmouse->pktcnt == 1 && psmouse->packet[0] == PSMOUSE_RET_BAT) {
queue_task(&psmouse->tq, &tq_immediate);
mark_bh(IMMEDIATE_BH);
return;
}
}
/*
* psmouse_sendbyte() sends a byte to the mouse, and waits for acknowledge.
* It doesn't handle retransmission, though it could - because when there would
* be need for retransmissions, the mouse has to be replaced anyway.
*/
static int psmouse_sendbyte(struct psmouse *psmouse, unsigned char byte)
{
int timeout = 1000; /* 10 msec */
psmouse->ack = 0;
psmouse->acking = 1;
serio_write(psmouse->serio, byte);
while (!psmouse->ack && timeout--) udelay(10);
return -(psmouse->ack <= 0);
}
/*
* psmouse_command() sends a command and its parameters to the mouse,
* then waits for the response and puts it in the param array.
*/
static int psmouse_command(struct psmouse *psmouse, unsigned char *param, int command)
{
int timeout = 100000; /* 100 msec */
int send = (command >> 12) & 0xf;
int receive = (command >> 8) & 0xf;
int i;
psmouse->cmdcnt = receive;
if (command & 0xff)
if (psmouse_sendbyte(psmouse, command & 0xff))
return (psmouse->cmdcnt = 0) - 1;
for (i = 0; i < send; i++)
if (psmouse_sendbyte(psmouse, param[i]))
return (psmouse->cmdcnt = 0) - 1;
while (psmouse->cmdcnt && timeout--) udelay(1);
for (i = 0; i < receive; i++)
param[i] = psmouse->cmdbuf[(receive - 1) - i];
if (psmouse->cmdcnt)
return (psmouse->cmdcnt = 0) - 1;
return 0;
}
/*
* psmouse_ps2pp_cmd() sends a PS2++ command, sliced into two bit
* pieces through the SETRES command. This is needed to send extended
* commands to mice on notebooks that try to understand the PS/2 protocol
* Ugly.
*/
static int psmouse_ps2pp_cmd(struct psmouse *psmouse, unsigned char *param, unsigned char command)
{
unsigned char d;
int i;
if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11))
return -1;
for (i = 6; i >= 0; i -= 2) {
d = (command >> i) & 3;
if(psmouse_command(psmouse, &d, PSMOUSE_CMD_SETRES))
return -1;
}
if (psmouse_command(psmouse, param, PSMOUSE_CMD_POLL))
return -1;
return 0;
}
/*
* psmouse_extensions() probes for any extensions to the basic PS/2 protocol
* the mouse may have.
*/
static int psmouse_extensions(struct psmouse *psmouse)
{
unsigned char param[4];
param[0] = 0;
psmouse->vendor = "Generic";
psmouse->name = "Mouse";
/*
* Try Genius NetMouse magic init.
*/
param[0] = 3;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
if (param[0] == 0x00 && param[1] == 0x33 && param[2] == 0x55) {
psmouse->vendor = "Genius";
psmouse->name = "Mouse";
set_bit(BTN_EXTRA, psmouse->dev.keybit);
set_bit(BTN_SIDE, psmouse->dev.keybit);
set_bit(REL_WHEEL, psmouse->dev.relbit);
return PSMOUSE_GENPS;
}
/*
* Try Logitech magic ID.
*/
param[0] = 0;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
psmouse_command(psmouse, param, PSMOUSE_CMD_GETINFO);
if (param[1]) {
int i;
static int logitech_4btn[] = { 12, 40, 41, 42, 43, 73, 80, -1 };
static int logitech_wheel[] = { 75, 76, 80, 81, 83, 88, -1 };
static int logitech_ps2pp[] = { 12, 13, 40, 41, 42, 43, 50, 51, 52, 53, 73, 75,
76, 80, 81, 83, 88, 96, 97, -1 };
int devicetype = ((param[0] >> 4) & 0x07) | ((param[0] << 3) & 0x78);
psmouse->vendor = "Logitech";
psmouse->name = "Mouse";
if (param[1] < 3)
clear_bit(BTN_MIDDLE, psmouse->dev.keybit);
if (param[1] < 2)
clear_bit(BTN_RIGHT, psmouse->dev.keybit);
psmouse->type = PSMOUSE_PS2;
for (i = 0; logitech_ps2pp[i] != -1; i++)
if (logitech_ps2pp[i] == devicetype) psmouse->type = PSMOUSE_PS2PP;
if (psmouse->type != PSMOUSE_PS2PP) return PSMOUSE_PS2;
for (i = 0; logitech_4btn[i] != -1; i++)
if (logitech_4btn[i] == devicetype) set_bit(BTN_SIDE, psmouse->dev.keybit);
for (i = 0; logitech_wheel[i] != -1; i++)
if (logitech_wheel[i] == devicetype) set_bit(REL_WHEEL, psmouse->dev.relbit);
/*
* Do Logitech PS2++ / PS2T++ magic init.
*/
if (devicetype == 97) { /* TouchPad 3 */
set_bit(REL_WHEEL, psmouse->dev.relbit);
set_bit(REL_HWHEEL, psmouse->dev.relbit);
param[0] = 0x11; param[1] = 0x04; param[2] = 0x68; /* Unprotect RAM */
psmouse_command(psmouse, param, 0x30d1);
param[0] = 0x11; param[1] = 0x05; param[2] = 0x0b; /* Enable features */
psmouse_command(psmouse, param, 0x30d1);
param[0] = 0x11; param[1] = 0x09; param[2] = 0xc3; /* Enable PS2++ */
psmouse_command(psmouse, param, 0x30d1);
param[0] = 0;
if (!psmouse_command(psmouse, param, 0x13d1) &&
param[0] == 0x06 && param[1] == 0x00 && param[2] == 0x14)
return PSMOUSE_PS2TPP;
} else {
psmouse_ps2pp_cmd(psmouse, param, 0x39); /* Magic knock */
psmouse_ps2pp_cmd(psmouse, param, 0xDB);
if ((param[0] & 0x78) == 0x48 && (param[1] & 0xf3) == 0xc2 &&
(param[2] & 3) == ((param[1] >> 2) & 3))
return PSMOUSE_PS2PP;
}
}
/*
* Try IntelliMouse magic init.
*/
param[0] = 200;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
param[0] = 100;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
param[0] = 80;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
psmouse_command(psmouse, param, PSMOUSE_CMD_GETID);
if (param[0] == 3) {
set_bit(REL_WHEEL, psmouse->dev.relbit);
/*
* Try IntelliMouse Explorer magic init.
*/
param[0] = 200;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
param[0] = 200;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
param[0] = 80;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
psmouse_command(psmouse, param, PSMOUSE_CMD_GETID);
if (param[0] == 4) {
psmouse->vendor = "Microsoft";
psmouse->name = "IntelliMouse Explorer";
set_bit(BTN_SIDE, psmouse->dev.keybit);
set_bit(BTN_EXTRA, psmouse->dev.keybit);
return PSMOUSE_IMEX;
}
psmouse->vendor = "Microsoft";
psmouse->name = "IntelliMouse";
return PSMOUSE_IMPS;
}
/*
* Okay, all failed, we have a standard mouse here. The number of the buttons is
* still a question, though.
*/
psmouse->vendor = "Generic";
psmouse->name = "Mouse";
return PSMOUSE_PS2;
}
/*
* psmouse_probe() probes for a PS/2 mouse.
*/
static int psmouse_probe(struct psmouse *psmouse)
{
unsigned char param[2];
/*
* First we reset and disable the mouse.
*/
if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_RESET_DIS))
return -1;
/*
* Next, we check if it's a mouse. It should send 0x00 or 0x03
* in case of an IntelliMouse in 4-byte mode or 0x04 for IM Explorer.
*/
param[0] = param[1] = 0xa5;
if (psmouse_command(psmouse, param, PSMOUSE_CMD_GETID))
return -1;
if (param[0] != 0x00 && param[0] != 0x03 && param[0] != 0x04)
return -1;
/*
* And here we try to determine if it has any extensions over the
* basic PS/2 3-button mouse.
*/
return psmouse->type = psmouse_extensions(psmouse);
}
/*
* psmouse_initialize() initializes the mouse to a sane state.
*/
static void psmouse_initialize(struct psmouse *psmouse)
{
unsigned char param[2];
/*
* We set the mouse report rate to a highest possible value.
* We try 100 first in case mouse fails to set 200.
*/
param[0] = 100;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
param[0] = 200;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRATE);
/*
* We also set the resolution and scaling.
*/
param[0] = 3;
psmouse_command(psmouse, param, PSMOUSE_CMD_SETRES);
psmouse_command(psmouse, NULL, PSMOUSE_CMD_SETSCALE11);
/*
* We set the mouse into streaming mode.
*/
psmouse_command(psmouse, param, PSMOUSE_CMD_SETSTREAM);
/*
* Last, we enable the mouse so that we get reports from it.
*/
if (psmouse_command(psmouse, NULL, PSMOUSE_CMD_ENABLE)) {
printk(KERN_WARNING "psmouse.c: Failed to enable mouse on %s\n", psmouse->serio->phys);
}
}
/*
* psmouse_disconnect() cleans up after we don't want talk
* to the mouse anymore.
*/
static void psmouse_disconnect(struct serio *serio)
{
struct psmouse *psmouse = serio->private;
input_unregister_device(&psmouse->dev);
serio_close(serio);
kfree(psmouse);
}
/*
* psmouse_powerup() is called when we get the powerup
* sequence - 0xaa [0x00], so that the mouse/kbd is re-probed.
*/
static void psmouse_powerup(void *data)
{
struct psmouse *psmouse = data;
if (psmouse->packet[0] == PSMOUSE_RET_BAT && (psmouse->pktcnt == 1 ||
(psmouse->pktcnt == 2 && psmouse->packet[1] == 0x00))) {
mdelay(40); /* FIXME!!! Wait some nicer way */
serio_rescan(psmouse->serio);
}
}
/*
* psmouse_connect() is a callback form the serio module when
* an unhandled serio port is found.
*/
static void psmouse_connect(struct serio *serio, struct serio_dev *dev)
{
struct psmouse *psmouse;
if ((serio->type & SERIO_TYPE) != SERIO_8042)
return;
if (!(psmouse = kmalloc(sizeof(struct psmouse), GFP_KERNEL)))
return;
memset(psmouse, 0, sizeof(struct psmouse));
psmouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
psmouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
psmouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
psmouse->serio = serio;
psmouse->dev.private = psmouse;
psmouse->tq.routine = psmouse_powerup;
psmouse->tq.data = psmouse;
serio->private = psmouse;
if (serio_open(serio, dev)) {
kfree(psmouse);
return;
}
if (psmouse_probe(psmouse) <= 0) {
serio_close(serio);
kfree(psmouse);
return;
}
sprintf(psmouse->devname, "%s %s %s",
psmouse_protocols[psmouse->type], psmouse->vendor, psmouse->name);
sprintf(psmouse->phys, "%s/input0",
serio->phys);
psmouse->dev.name = psmouse->devname;
psmouse->dev.phys = psmouse->phys;
psmouse->dev.idbus = BUS_I8042;
psmouse->dev.idvendor = psmouse->type;
psmouse->dev.idproduct = 0x0002;
psmouse->dev.idversion = 0x0100;
input_register_device(&psmouse->dev);
printk(KERN_INFO "input: %s on %s\n", psmouse->devname, serio->phys);
psmouse_initialize(psmouse);
}
static struct serio_dev psmouse_dev = {
interrupt: psmouse_interrupt,
connect: psmouse_connect,
disconnect: psmouse_disconnect
};
int __init psmouse_init(void)
{
serio_register_device(&psmouse_dev);
return 0;
}
void __exit psmouse_exit(void)
{
serio_unregister_device(&psmouse_dev);
}
module_init(psmouse_init);
module_exit(psmouse_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:48:17
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/mouse
In directory usw-pr-cvs1:/tmp/cvs-serv14032
Added Files:
Tag: 1.13
pc110pad.c
Log Message:
Moved.
--- NEW FILE: pc110pad.c ---
/*
* $Id: pc110pad.c,v 1.13 2002/01/22 20:48:14 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
* Alan Cox Robin O'Leary
*/
/*
* IBM PC110 touchpad 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/ioport.h>
#include <linux/input.h>
#include <linux/init.h>
#include <asm/io.h>
#include <asm/irq.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>");
MODULE_DESCRIPTION("IBM PC110 touchpad driver");
MODULE_LICENSE("GPL");
#define PC110PAD_OFF 0x30
#define PC110PAD_ON 0x38
static int pc110pad_irq = 10;
static int pc110pad_io = 0x15e0;
static struct input_dev pc110pad_dev;
static int pc110pad_data[3];
static int pc110pad_count;
static int pc110pad_used;
static char *pc110pad_name = "IBM PC110 TouchPad";
static char *pc110pad_phys = "isa15e0/input0";
static void pc110pad_interrupt(int irq, void *ptr, struct pt_regs *regs)
{
int value = inb_p(pc110pad_io);
int handshake = inb_p(pc110pad_io + 2);
outb_p(handshake | 1, pc110pad_io + 2);
outb_p(handshake & ~1, pc110pad_io + 2);
inb_p(0x64);
pc110pad_data[pc110pad_count++] = value;
if (pc110pad_count < 3) return;
input_report_key(&pc110pad_dev, BTN_TOUCH,
pc110pad_data[0] & 0x01);
input_report_abs(&pc110pad_dev, ABS_X,
pc110pad_data[1] | ((pc110pad_data[0] << 3) & 0x80) | ((pc110pad_data[0] << 1) & 0x100));
input_report_abs(&pc110pad_dev, ABS_Y,
pc110pad_data[2] | ((pc110pad_data[0] << 4) & 0x80));
pc110pad_count = 0;
}
static void pc110pad_close(struct input_dev *dev)
{
if (!--pc110pad_used)
outb(PC110PAD_OFF, pc110pad_io + 2);
}
static int pc110pad_open(struct input_dev *dev)
{
unsigned long flags;
if (pc110pad_used++)
return 0;
save_flags(flags);
cli();
pc110pad_interrupt(0,0,0);
pc110pad_interrupt(0,0,0);
pc110pad_interrupt(0,0,0);
outb(PC110PAD_ON, pc110pad_io + 2);
pc110pad_count = 0;
restore_flags(flags);
return 0;
}
static int __init pc110pad_init(void)
{
if (request_region(pc110pad_io, 4, "pc110pad"))
{
printk(KERN_ERR "pc110pad: I/O area %#x-%#x in use.\n", pc110pad_io, pc110pad_io + 4);
return -EBUSY;
}
outb(PC110PAD_OFF, pc110pad_io + 2);
if (request_irq(pc110pad_irq, pc110pad_interrupt, 0, "pc110pad", 0))
{
release_region(pc110pad_io, 4);
printk(KERN_ERR "pc110pad: Unable to get irq %d.\n", pc110pad_irq);
return -EBUSY;
}
pc110pad_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
pc110pad_dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
pc110pad_dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
pc110pad_dev.absmax[ABS_X] = 0x1ff;
pc110pad_dev.absmax[ABS_Y] = 0x0ff;
pc110pad_dev.open = pc110pad_open;
pc110pad_dev.close = pc110pad_close;
pc110pad_dev.name = pc110pad_name;
pc110pad_dev.phys = pc110pad_phys;
pc110pad_dev.idbus = BUS_ISA;
pc110pad_dev.idvendor = 0x0003;
pc110pad_dev.idproduct = 0x0001;
pc110pad_dev.idversion = 0x0100;
input_register_device(&pc110pad_dev);
printk(KERN_INFO "input: %s at %#x irq %d\n",
pc110pad_name, pc110pad_io, pc110pad_irq);
return 0;
}
static void __exit pc110pad_exit(void)
{
input_unregister_device(&pc110pad_dev);
outb(PC110PAD_OFF, pc110pad_io + 2);
free_irq(pc110pad_irq, 0);
release_region(pc110pad_io, 4);
}
module_init(pc110pad_init);
module_exit(pc110pad_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:47:48
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/mouse
In directory usw-pr-cvs1:/tmp/cvs-serv13744
Added Files:
Tag: 1.2
maplemouse.c
Log Message:
Moved.
--- NEW FILE: maplemouse.c ---
/*
* $Id: maplemouse.c,v 1.2 2002/01/22 20:47:45 vojtech Exp $
* SEGA Dreamcast mouse driver
* Based on drivers/usb/usbmouse.c
*/
#include <linux/kernel.h>
#include <linux/malloc.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/timer.h>
#include <linux/maple.h>
MODULE_AUTHOR("YAEGASHI Takeshi <t...@ke...>");
MODULE_DESCRIPTION("SEGA Dreamcast mouse driver");
struct dc_mouse {
struct input_dev dev;
int open;
};
static void dc_mouse_callback(struct mapleq *mq)
{
int buttons, relx, rely, relz;
struct maple_device *mapledev = mq->dev;
struct dc_mouse *mouse = mapledev->private_data;
struct input_dev *dev = &mouse->dev;
unsigned char *res = mq->recvbuf;
buttons = ~res[8];
relx=*(unsigned short *)(res+12)-512;
rely=*(unsigned short *)(res+14)-512;
relz=*(unsigned short *)(res+16)-512;
input_report_key(dev, BTN_LEFT, buttons&4);
input_report_key(dev, BTN_MIDDLE, buttons&9);
input_report_key(dev, BTN_RIGHT, buttons&2);
input_report_rel(dev, REL_X, relx);
input_report_rel(dev, REL_Y, rely);
input_report_rel(dev, REL_WHEEL, relz);
}
static int dc_mouse_open(struct input_dev *dev)
{
struct dc_mouse *mouse = dev->private;
mouse->open++;
return 0;
}
static void dc_mouse_close(struct input_dev *dev)
{
struct dc_mouse *mouse = dev->private;
mouse->open--;
}
static int dc_mouse_connect(struct maple_device *dev)
{
unsigned long data = be32_to_cpu(dev->devinfo.function_data[0]);
struct dc_mouse *mouse;
if (!(mouse = kmalloc(sizeof(struct dc_mouse), GFP_KERNEL)))
return -1;
memset(mouse, 0, sizeof(struct dc_mouse));
dev->private_data = mouse;
mouse->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
mouse->dev.keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
mouse->dev.relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
mouse->dev.private = mouse;
mouse->dev.open = dc_mouse_open;
mouse->dev.close = dc_mouse_close;
mouse->dev.event = NULL;
mouse->dev.name = dev->product_name;
mouse->dev.idbus = BUS_MAPLE;
input_register_device(&mouse->dev);
maple_getcond_callback(dev, dc_mouse_callback, 1, MAPLE_FUNC_MOUSE);
printk(KERN_INFO "input%d: mouse(0x%lx): %s\n",
mouse->dev.number, data, mouse->dev.name);
MOD_INC_USE_COUNT;
return 0;
}
static void dc_mouse_disconnect(struct maple_device *dev)
{
struct dc_mouse *mouse = dev->private_data;
input_unregister_device(&mouse->dev);
kfree(mouse);
MOD_DEC_USE_COUNT;
}
static struct maple_driver dc_mouse_driver = {
function: MAPLE_FUNC_MOUSE,
name: "Dreamcast mouse",
connect: dc_mouse_connect,
disconnect: dc_mouse_disconnect,
};
static int __init dc_mouse_init(void)
{
maple_register_driver(&dc_mouse_driver);
return 0;
}
static void __exit dc_mouse_exit(void)
{
maple_unregister_driver(&dc_mouse_driver);
}
module_init(dc_mouse_init);
module_exit(dc_mouse_exit);
/*
* Local variables:
* c-basic-offset: 8
* End:
*/
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:47:35
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/mouse
In directory usw-pr-cvs1:/tmp/cvs-serv13642
Added Files:
Tag: 1.12
logibm.c
Log Message:
Moved.
--- NEW FILE: logibm.c ---
/*
* $Id: logibm.c,v 1.12 2002/01/22 20:47:32 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
* James Banks Matthew Dillon
* David Giller Nathan Laredo
* Linus Torvalds Johan Myreen
* Cliff Matthews Philip Blundell
* Russell King
*/
/*
* Logitech Bus Mouse 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/input.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>");
MODULE_DESCRIPTION("Logitech busmouse driver");
MODULE_LICENSE("GPL");
#define LOGIBM_BASE 0x23c
#define LOGIBM_EXTENT 4
#define LOGIBM_DATA_PORT LOGIBM_BASE + 0
#define LOGIBM_SIGNATURE_PORT LOGIBM_BASE + 1
#define LOGIBM_CONTROL_PORT LOGIBM_BASE + 2
#define LOGIBM_CONFIG_PORT LOGIBM_BASE + 3
#define LOGIBM_ENABLE_IRQ 0x00
#define LOGIBM_DISABLE_IRQ 0x10
#define LOGIBM_READ_X_LOW 0x80
#define LOGIBM_READ_X_HIGH 0xa0
#define LOGIBM_READ_Y_LOW 0xc0
#define LOGIBM_READ_Y_HIGH 0xe0
#define LOGIBM_DEFAULT_MODE 0x90
#define LOGIBM_CONFIG_BYTE 0x91
#define LOGIBM_SIGNATURE_BYTE 0xa5
#define LOGIBM_IRQ 5
MODULE_PARM(logibm_irq, "i");
static int logibm_irq = LOGIBM_IRQ;
static int logibm_used = 0;
static void logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int logibm_open(struct input_dev *dev)
{
if (logibm_used++)
return 0;
if (request_irq(logibm_irq, logibm_interrupt, 0, "logibm", NULL)) {
logibm_used--;
printk(KERN_ERR "logibm.c: Can't allocate irq %d\n", logibm_irq);
return -EBUSY;
}
outb(LOGIBM_ENABLE_IRQ, LOGIBM_CONTROL_PORT);
return 0;
}
static void logibm_close(struct input_dev *dev)
{
if (--logibm_used)
return;
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
free_irq(logibm_irq, NULL);
}
static struct input_dev logibm_dev = {
evbit: { BIT(EV_KEY) | BIT(EV_REL) },
keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
relbit: { BIT(REL_X) | BIT(REL_Y) },
open: logibm_open,
close: logibm_close,
name: "Logitech bus mouse",
phys: "isa023c/input0",
idbus: BUS_ISA,
idvendor: 0x0003,
idproduct: 0x0001,
idversion: 0x0100,
};
static void logibm_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
char dx, dy;
unsigned char buttons;
outb(LOGIBM_READ_X_LOW, LOGIBM_CONTROL_PORT);
dx = (inb(LOGIBM_DATA_PORT) & 0xf);
outb(LOGIBM_READ_X_HIGH, LOGIBM_CONTROL_PORT);
dx |= (inb(LOGIBM_DATA_PORT) & 0xf) << 4;
outb(LOGIBM_READ_Y_LOW, LOGIBM_CONTROL_PORT);
dy = (inb(LOGIBM_DATA_PORT) & 0xf);
outb(LOGIBM_READ_Y_HIGH, LOGIBM_CONTROL_PORT);
buttons = inb(LOGIBM_DATA_PORT);
dy |= (buttons & 0xf) << 4;
buttons = ~buttons;
input_report_rel(&logibm_dev, REL_X, dx);
input_report_rel(&logibm_dev, REL_Y, 255 - dy);
input_report_key(&logibm_dev, BTN_MIDDLE, buttons & 1);
input_report_key(&logibm_dev, BTN_LEFT, buttons & 2);
input_report_key(&logibm_dev, BTN_RIGHT, buttons & 4);
}
#ifndef MODULE
static int __init logibm_setup(char *str)
{
int ints[4];
str = get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0) logibm_irq = ints[1];
return 1;
}
__setup("logibm_irq=", logibm_setup);
#endif
static int __init logibm_init(void)
{
if (request_region(LOGIBM_BASE, LOGIBM_EXTENT, "logibm")) {
printk(KERN_ERR "logibm.c: Can't allocate ports at %#x\n", LOGIBM_BASE);
return -EBUSY;
}
outb(LOGIBM_CONFIG_BYTE, LOGIBM_CONFIG_PORT);
outb(LOGIBM_SIGNATURE_BYTE, LOGIBM_SIGNATURE_PORT);
udelay(100);
if (inb(LOGIBM_SIGNATURE_PORT) != LOGIBM_SIGNATURE_BYTE) {
release_region(LOGIBM_BASE, LOGIBM_EXTENT);
printk(KERN_ERR "logibm.c: Didn't find Logitech busmouse at %#x\n", LOGIBM_BASE);
return -ENODEV;
}
outb(LOGIBM_DEFAULT_MODE, LOGIBM_CONFIG_PORT);
outb(LOGIBM_DISABLE_IRQ, LOGIBM_CONTROL_PORT);
input_register_device(&logibm_dev);
printk(KERN_INFO "input: Logitech bus mouse at %#x irq %d\n", LOGIBM_BASE, logibm_irq);
return 0;
}
static void __exit logibm_exit(void)
{
input_unregister_device(&logibm_dev);
release_region(LOGIBM_BASE, LOGIBM_EXTENT);
}
module_init(logibm_init);
module_exit(logibm_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:47:17
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/mouse
In directory usw-pr-cvs1:/tmp/cvs-serv13456
Added Files:
Tag: 1.12
inport.c
Log Message:
Moved.
--- NEW FILE: inport.c ---
/*
* $Id: inport.c,v 1.12 2002/01/22 20:47:14 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*
* Based on the work of:
* Teemu Rantanen Derrick Cole
* Peter Cervasio Christoph Niemann
* Philip Blundell Russell King
* Bob Harris
*/
/*
* Inport (ATI XL and Microsoft) busmouse 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/io.h>
#include <asm/irq.h>
#include <linux/module.h>
#include <linux/config.h>
#include <linux/ioport.h>
#include <linux/init.h>
#include <linux/input.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>");
MODULE_DESCRIPTION("Inport (ATI XL and Microsoft) busmouse driver");
MODULE_LICENSE("GPL");
#define INPORT_BASE 0x23c
#define INPORT_EXTENT 4
#define INPORT_CONTROL_PORT INPORT_BASE + 0
#define INPORT_DATA_PORT INPORT_BASE + 1
#define INPORT_SIGNATURE_PORT INPORT_BASE + 2
#define INPORT_REG_BTNS 0x00
#define INPORT_REG_X 0x01
#define INPORT_REG_Y 0x02
#define INPORT_REG_MODE 0x07
#define INPORT_RESET 0x80
#ifdef CONFIG_INPUT_ATIXL
#define INPORT_NAME "ATI XL Mouse"
#define INPORT_VENDOR 0x0002
#define INPORT_SPEED_30HZ 0x01
#define INPORT_SPEED_50HZ 0x02
#define INPORT_SPEED_100HZ 0x03
#define INPORT_SPEED_200HZ 0x04
#define INPORT_MODE_BASE INPORT_SPEED_100HZ
#define INPORT_MODE_IRQ 0x08
#else
#define INPORT_NAME "Microsoft InPort Mouse"
#define INPORT_VENDOR 0x0001
#define INPORT_MODE_BASE 0x10
#define INPORT_MODE_IRQ 0x01
#endif
#define INPORT_MODE_HOLD 0x20
#define INPORT_IRQ 5
MODULE_PARM(inport_irq, "i");
static int inport_irq = INPORT_IRQ;
static int inport_used = 0;
static void inport_interrupt(int irq, void *dev_id, struct pt_regs *regs);
static int inport_open(struct input_dev *dev)
{
if (!inport_used++) {
if (request_irq(inport_irq, inport_interrupt, 0, "inport", NULL))
return -EBUSY;
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
}
return 0;
}
static void inport_close(struct input_dev *dev)
{
if (!--inport_used) {
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
free_irq(inport_irq, NULL);
}
}
static struct input_dev inport_dev = {
evbit: { BIT(EV_KEY) | BIT(EV_REL) },
keybit: { [LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT) },
relbit: { BIT(REL_X) | BIT(REL_Y) },
open: inport_open,
close: inport_close,
name: INPORT_NAME,
phys: "isa023c/input0",
idbus: BUS_ISA,
idvendor: INPORT_VENDOR,
idproduct: 0x0001,
idversion: 0x0100,
};
static void inport_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
unsigned char buttons;
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_HOLD | INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
outb(INPORT_REG_X, INPORT_CONTROL_PORT);
input_report_rel(&inport_dev, REL_X, inb(INPORT_DATA_PORT));
outb(INPORT_REG_Y, INPORT_CONTROL_PORT);
input_report_rel(&inport_dev, REL_Y, inb(INPORT_DATA_PORT));
outb(INPORT_REG_BTNS, INPORT_CONTROL_PORT);
buttons = inb(INPORT_DATA_PORT);
input_report_key(&inport_dev, BTN_MIDDLE, buttons & 1);
input_report_key(&inport_dev, BTN_LEFT, buttons & 2);
input_report_key(&inport_dev, BTN_RIGHT, buttons & 4);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_IRQ | INPORT_MODE_BASE, INPORT_DATA_PORT);
}
#ifndef MODULE
static int __init inport_setup(char *str)
{
int ints[4];
str = get_options(str, ARRAY_SIZE(ints), ints);
if (ints[0] > 0) inport_irq = ints[1];
return 1;
}
__setup("inport_irq=", inport_setup);
#endif
static int __init inport_init(void)
{
unsigned char a,b,c;
if (check_region(INPORT_BASE, INPORT_EXTENT))
return -EBUSY;
a = inb(INPORT_SIGNATURE_PORT);
b = inb(INPORT_SIGNATURE_PORT);
c = inb(INPORT_SIGNATURE_PORT);
if (( a == b ) || ( a != c ))
return -ENODEV;
outb(INPORT_RESET, INPORT_CONTROL_PORT);
outb(INPORT_REG_MODE, INPORT_CONTROL_PORT);
outb(INPORT_MODE_BASE, INPORT_DATA_PORT);
request_region(INPORT_BASE, INPORT_EXTENT, "inport");
input_register_device(&inport_dev);
printk(KERN_INFO "input: " INPORT_NAME " at %#x irq %d\n",
INPORT_BASE, inport_irq);
return 0;
}
static void __exit inport_exit(void)
{
input_unregister_device(&inport_dev);
release_region(INPORT_BASE, INPORT_EXTENT);
}
module_init(inport_init);
module_exit(inport_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:47:01
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/mouse
In directory usw-pr-cvs1:/tmp/cvs-serv13294
Added Files:
Tag: 1.13
gunze.c
Log Message:
Moved.
--- NEW FILE: gunze.c ---
/*
* $Id: gunze.c,v 1.13 2002/01/22 20:46:58 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*/
/*
* Gunze AHL-51S touchscreen 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/serio.h>
#include <linux/init.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>");
MODULE_DESCRIPTION("Gunze AHL-51S touchscreen driver");
MODULE_LICENSE("GPL");
/*
* Definitions & global arrays.
*/
#define GUNZE_MAX_LENGTH 10
static char *gunze_name = "Gunze AHL-51S TouchScreen";
/*
* Per-touchscreen data.
*/
struct gunze {
struct input_dev dev;
struct serio *serio;
int idx;
unsigned char data[GUNZE_MAX_LENGTH];
char phys[32];
};
static void gunze_process_packet(struct gunze* gunze)
{
struct input_dev *dev = &gunze->dev;
if (gunze->idx != GUNZE_MAX_LENGTH || gunze->data[5] != ',' ||
(gunze->data[0] != 'T' && gunze->data[0] != 'R')) {
gunze->data[10] = 0;
printk(KERN_WARNING "gunze.c: bad packet: >%s<\n", gunze->data);
return;
}
input_report_abs(dev, ABS_X, simple_strtoul(gunze->data + 1, NULL, 10) * 4);
input_report_abs(dev, ABS_Y, 3072 - simple_strtoul(gunze->data + 6, NULL, 10) * 3);
input_report_key(dev, BTN_TOUCH, gunze->data[0] == 'T');
}
static void gunze_interrupt(struct serio *serio, unsigned char data, unsigned int flags)
{
struct gunze* gunze = serio->private;
if (data == '\r') {
gunze_process_packet(gunze);
gunze->idx = 0;
} else {
if (gunze->idx < GUNZE_MAX_LENGTH)
gunze->data[gunze->idx++] = data;
}
}
/*
* gunze_disconnect() is the opposite of gunze_connect()
*/
static void gunze_disconnect(struct serio *serio)
{
struct gunze* gunze = serio->private;
input_unregister_device(&gunze->dev);
serio_close(serio);
kfree(gunze);
}
/*
* gunze_connect() is the routine that is called when someone adds a
* new serio device. It looks whether it was registered as a Gunze touchscreen
* and if yes, registers it as an input device.
*/
static void gunze_connect(struct serio *serio, struct serio_dev *dev)
{
struct gunze *gunze;
if (serio->type != (SERIO_RS232 | SERIO_GUNZE))
return;
if (!(gunze = kmalloc(sizeof(struct gunze), GFP_KERNEL)))
return;
memset(gunze, 0, sizeof(struct gunze));
gunze->dev.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
gunze->dev.absbit[0] = BIT(ABS_X) | BIT(ABS_Y);
gunze->dev.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
gunze->dev.absmin[ABS_X] = 96; gunze->dev.absmin[ABS_Y] = 72;
gunze->dev.absmax[ABS_X] = 4000; gunze->dev.absmax[ABS_Y] = 3000;
gunze->serio = serio;
serio->private = gunze;
sprintf(gunze->phys, "%s/input0", serio->phys);
gunze->dev.private = gunze;
gunze->dev.name = gunze_name;
gunze->dev.phys = gunze->phys;
gunze->dev.idbus = BUS_RS232;
gunze->dev.idvendor = SERIO_GUNZE;
gunze->dev.idproduct = 0x0051;
gunze->dev.idversion = 0x0100;
if (serio_open(serio, dev)) {
kfree(gunze);
return;
}
input_register_device(&gunze->dev);
printk(KERN_INFO "input: %s on %s\n", gunze_name, serio->phys);
}
/*
* The serio device structure.
*/
static struct serio_dev gunze_dev = {
interrupt: gunze_interrupt,
connect: gunze_connect,
disconnect: gunze_disconnect,
};
/*
* The functions for inserting/removing us as a module.
*/
int __init gunze_init(void)
{
serio_register_device(&gunze_dev);
return 0;
}
void __exit gunze_exit(void)
{
serio_unregister_device(&gunze_dev);
}
module_init(gunze_init);
module_exit(gunze_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:46:48
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/mouse
In directory usw-pr-cvs1:/tmp/cvs-serv13183
Added Files:
Tag: 1.10
amimouse.c
Log Message:
Moved.
--- NEW FILE: amimouse.c ---
/*
* $Id: amimouse.c,v 1.10 2002/01/22 20:46:45 vojtech Exp $
*
* Copyright (c) 2000-2001 Vojtech Pavlik
*
* Based on the work of:
* Michael Rausch James Banks
* Matther Dillon David Giller
* Nathan Laredo Linus Torvalds
* Johan Myreen Jes Sorensen
* Russel King
*/
/*
* Amiga mouse driver for Linux/m68k
*/
/*
* 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/input.h>
#include <asm/irq.h>
#include <asm/setup.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <asm/amigahw.h>
#include <asm/amigaints.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>");
MODULE_DESCRIPTION("Amiga mouse driver");
MODULE_LICENSE("GPL");
static int amimouse_used = 0;
static int amimouse_lastx, amimouse_lasty;
static struct input_dev amimouse_dev;
static char *amimouse_name = "Amiga mouse";
static char *amimouse_phys = "amimouse/input0";
static void amimouse_interrupt(int irq, void *dummy, struct pt_regs *fp)
{
unsigned short joy0dat, potgor;
int nx, ny, dx, dy;
joy0dat = custom.joy0dat;
nx = joy0dat & 0xff;
ny = joy0dat >> 8;
dx = nx - amimouse_lastx;
dy = ny - amimouse_lasty;
if (dx < -127) dx = (256 + nx) - lastx;
if (dx > 127) dx = (nx - 256) - lastx;
if (dy < -127) dy = (256 + ny) - lasty;
if (dy > 127) dy = (ny - 256) - lasty;
amimouse_lastx = nx;
amimouse_lasty = ny;
potgor = custom.potgor;
input_report_rel(&amimouse_dev, REL_X, dx);
input_report_rel(&amimouse_dev, REL_Y, dy);
input_report_key(&amimouse_dev, BTN_LEFT, ciaa.pra & 0x40);
input_report_key(&amimouse_dev, BTN_MIDDLE, potgor & 0x0100);
input_report_key(&amimouse_dev, BTN_RIGHT, potgor & 0x0400);
}
static int amimouse_open(struct input_dev *dev)
{
unsigned short joy0dat;
if (amimouse_used++)
return 0;
joy0dat = custom.joy0dat;
amimouse_lastx = joy0dat & 0xff;
amimouse_lasty = joy0dat >> 8;
if (request_irq(IRQ_AMIGA_VERTB, amimouse_interrupt, 0, "amimouse", NULL)) {
amimouse_used--;
printk(KERN_ERR "amimouse.c: Can't allocate irq %d\n", amimouse_irq);
return -EBUSY;
}
return 0;
}
static void amimouse_close(struct input_dev *dev)
{
if (!--amimouse_used)
free_irq(IRQ_AMIGA_VERTB, amimouse_interrupt);
}
static int __init amimouse_init(void)
{
if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_MOUSE))
return -ENODEV;
amimouse_dev.evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
amimouse_dev.relbit[0] = BIT(REL_X) | BIT(REL_Y);
amimouse_dev.keybit[LONG(BTN_LEFT)] = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT);
amimouse_dev.open = amimouse_open;
amimouse_dev.close = amimouse_close;
amimouse_dev.name = amimouse_name;
amimouse_dev.phys = amimouse_phys;
amimouse_dev.idbus = BUS_AMIGA;
amimouse_dev.idvendor = 0x0001;
amimouse_dev.idproduct = 0x0002;
amimouse_dev.idversion = 0x0100;
input_register_device(&amimouse_dev);
printk(KERN_INFO "input: %s at joy0dat\n", amimouse_name);
}
static void __exit amimouse_exit(void)
{
input_unregister_device(&amimouse_dev);
}
module_init(amimouse_init);
module_exit(amimouse_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:45:19
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/serio
In directory usw-pr-cvs1:/tmp/cvs-serv12560
Modified Files:
Tag: 1.9
serport_old.c
Log Message:
Moved.
--- NEW FILE: serport_old.c ---
/*
* $Id: serport_old.c,v 1.9 2002/01/22 20:45:17 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* This is a module that converts a tty line into a much simpler
* 'serial io port' abstraction that the input device drivers use.
*/
/*
* 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/tty.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>");
MODULE_DESCRIPTION("Input device TTY line discipline");
MODULE_LICENSE("GPL");
struct serport {
struct tty_struct *tty;
wait_queue_head_t wait;
struct serio serio;
char phys[32];
};
char serport_name[] = "Serial port";
/*
* Callback functions from the serio code.
*/
static int serport_serio_write(struct serio *serio, unsigned char data)
{
struct serport *serport = serio->driver;
return -(serport->tty->driver.write(serport->tty, 0, &data, 1) != 1);
}
static int serport_serio_open(struct serio *serio)
{
return 0;
}
static void serport_serio_close(struct serio *serio)
{
struct serport *serport = serio->driver;
wake_up_interruptible(&serport->wait);
}
/*
* serport_ldisc_open() is the routine that is called upon setting our line
* discipline on a tty. It looks for the Mag, and if found, registers
* it as a joystick device.
*/
static int serport_ldisc_open(struct tty_struct *tty)
{
struct serport *serport;
char ttyname[64];
int i;
MOD_INC_USE_COUNT;
if (!(serport = kmalloc(sizeof(struct serport), GFP_KERNEL))) {
MOD_DEC_USE_COUNT;
return -ENOMEM;
}
memset(serport, 0, sizeof(struct serport));
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
serport->tty = tty;
tty->disc_data = serport;
strcpy(ttyname, tty->driver.name);
for (i = 0; ttyname[i] != 0 && ttyname[i] != '/'; i++);
ttyname[i] = 0;
sprintf(serport->phys, "%s%d/serio0", ttyname, MINOR(tty->device) - tty->driver.minor_start);
serport->serio.name = serport_name;
serport->serio.phys = serport->phys;
serport->serio.type = SERIO_RS232;
serport->serio.write = serport_serio_write;
serport->serio.open = serport_serio_open;
serport->serio.close = serport_serio_close;
serport->serio.driver = serport;
init_waitqueue_head(&serport->wait);
return 0;
}
/*
* serport_ldisc_close() is the opposite of serport_ldisc_open()
*/
static void serport_ldisc_close(struct tty_struct *tty)
{
struct serport *serport = (struct serport*) tty->disc_data;
kfree(serport);
MOD_DEC_USE_COUNT;
}
/*
* serport_ldisc_receive() is called by the low level tty driver when characters
* are ready for us. We forward the characters, one by one to the 'interrupt'
* routine.
*/
static void serport_ldisc_receive(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
{
struct serport *serport = (struct serport*) tty->disc_data;
int i;
for (i = 0; i < count; i++)
if (serport->serio.dev)
serport->serio.dev->interrupt(&serport->serio, cp[i], 0);
}
/*
* serport_ldisc_room() reports how much room we do have for receiving data.
* Although we in fact have infinite room, we need to specify some value
* here, and 256 seems to be reasonable.
*/
static int serport_ldisc_room(struct tty_struct *tty)
{
return 256;
}
/*
* serport_ldisc_read() just waits indefinitely if everything goes well.
* However, when the serio driver closes the serio port, it finishes,
* returning 0 characters.
*/
static ssize_t serport_ldisc_read(struct tty_struct * tty, struct file * file, unsigned char * buf, size_t nr)
{
struct serport *serport = (struct serport*) tty->disc_data;
DECLARE_WAITQUEUE(wait, current);
char name[32];
#ifdef CONFIG_DEVFS_FS
sprintf(name, tty->driver.name, MINOR(tty->device) - tty->driver.minor_start);
#else
sprintf(name, "%s%d", tty->driver.name, MINOR(tty->device) - tty->driver.minor_start);
#endif
serio_register_port(&serport->serio);
printk(KERN_INFO "serio: Serial port %s\n", name);
add_wait_queue(&serport->wait, &wait);
set_current_state(TASK_INTERRUPTIBLE);
while(serport->serio.type && !signal_pending(current)) schedule();
set_current_state(TASK_RUNNING);
remove_wait_queue(&serport->wait, &wait);
serio_unregister_port(&serport->serio);
return 0;
}
/*
* serport_ldisc_ioctl() allows to set the port protocol, and device ID
*/
static int serport_ldisc_ioctl(struct tty_struct * tty, struct file * file, unsigned int cmd, unsigned long arg)
{
struct serport *serport = (struct serport*) tty->disc_data;
switch (cmd) {
case SPIOCSTYPE:
return get_user(serport->serio.type, (unsigned long *) arg);
}
return -EINVAL;
}
static void serport_ldisc_write_wakeup(struct tty_struct * tty)
{
struct serport *sp = (struct serport *) tty->disc_data;
serio_dev_write_wakeup(&sp->serio);
}
/*
* The line discipline structure.
*/
static struct tty_ldisc serport_ldisc = {
name: "input",
open: serport_ldisc_open,
close: serport_ldisc_close,
read: serport_ldisc_read,
ioctl: serport_ldisc_ioctl,
receive_buf: serport_ldisc_receive,
receive_room: serport_ldisc_room,
write_wakeup: serport_ldisc_write_wakeup
};
/*
* The functions for insering/removing us as a module.
*/
int __init serport_init(void)
{
if (tty_register_ldisc(N_MOUSE, &serport_ldisc)) {
printk(KERN_ERR "serport.c: Error registering line discipline.\n");
return -ENODEV;
}
return 0;
}
void __exit serport_exit(void)
{
tty_register_ldisc(N_MOUSE, NULL);
}
module_init(serport_init);
module_exit(serport_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:45:07
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/serio
In directory usw-pr-cvs1:/tmp/cvs-serv12432
Modified Files:
Tag: 1.14
serport.c
Log Message:
Moved.
--- NEW FILE: serport.c ---
/*
* $Id: serport.c,v 1.14 2002/01/22 20:45:03 vojtech Exp $
*/
/*
* This is a module that converts a tty line into a much simpler
* 'serial io port' abstraction that the input device drivers use.
*/
/*
* 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
*/
#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/serio.h>
#include <linux/tty.h>
#include <linux/circ_buf.h>
static DECLARE_MUTEX(port_sem);
/*
* Callback functions from the serio code.
*/
static int serport_serio_write(struct serio *serio, unsigned char data)
{
struct uart_info *info = serio->driver;
unsigned long flags;
int retval = -1;
if (!info->xmit.buf)
return retval;
save_flags(flags); cli();
if (CIRC_SPACE(info->xmit.head, info->xmit.tail, UART_XMIT_SIZE) != 0) { info->xmit.buf[info->xmit.head] = ch;
info->xmit.head = (info->xmit.head + 1) & (UART_XMIT_SIZE - 1);
retval = 0;
}
restore_flags(flags);
return retval;
}
static int serport_serio_open(struct serio *serio)
{
struct uart_info *info = serio->driver;
int retval = -ENODEV;
/*
if (!try_inc_mod_count(drv->owner))
goto fail;
*/
if (!info)
goto out;
/*
* If the port is in the middle of closing, bail out now.
*/
if (info->flags & ASYNC_CLOSING) {
interruptible_sleep_on(&info->close_wait);
retval = (info->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS;
goto out;
}
/*
* Make sure the device is in D0 state.
*/
if (info->state->count == 1)
#ifdef CONFIG_PM
pm_send(info->state->pm, PM_RESUME, (void *)0);
#else
if (info->ops->pm)
info->ops->pm(info->port, 0, 3);
#endif
/*
* Start up the serial port
*/
retval = uart_startup(info);
if (retval)
goto out;
uart_change_speed(info, NULL);
out:
if (drv->owner)
__MOD_DEC_USE_COUNT(drv->owner);
fail:
return retval;
}
static void serport_serio_close(struct serio *serio)
{
struct uart_info *info = serio->private;
struct uart_state *state = info->state;
down(&state->count_sem);
save_flags(flags); cli();
if (state->count) {
restore_flags(flags);
up(&state->count_sem);
goto done;
}
info->flags |= ASYNC_CLOSING;
restore_flags(flags);
up(&state->count_sem);
/*
* At this point, we stop accepting input. To do this, we
* disable the receive line status interrupts.
*/
if (info->flags & ASYNC_INITIALIZED) {
info->ops->stop_rx(info->port);
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
* important if there is a transmit FIFO!
*/
uart_wait_until_sent(tty, info->timeout);
}
uart_shutdown(info);
info->event = 0;
if (info->blocked_open) {
if (info->state->close_delay) {
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(info->state->close_delay);
set_current_state(TASK_RUNNING);
}
wake_up_interruptible(&info->open_wait);
} else {
#ifdef CONFIG_PM
/*
* Put device into D3 state.
*/
pm_send(info->state->pm, PM_SUSPEND, (void *)3);
#else
if (info->ops->pm)
info->ops->pm(info->port, 3, 0);
#endif
}
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait);
done:
if (drv->owner)
__MOD_DEC_USE_COUNT(drv->owner);
}
/*
* The functions for insering/removing us as a module.
*/
int __init serport_init(void)
{
struct uart_driver *input;
uart_register_driver(&input)
return 0;
}
void __exit serport_exit(void)
{
uart_unregister_driver(&input);
}
module_init(serport_init);
module_exit(serport_exit);
|
|
From: Vojtech P. <vo...@us...> - 2002-01-22 20:44:13
|
Update of /cvsroot/linuxconsole/ruby/linux/drivers/input/serio
In directory usw-pr-cvs1:/tmp/cvs-serv12061
Modified Files:
Tag: 1.9
parkbd.c
Log Message:
Moved.
--- NEW FILE: parkbd.c ---
/*
* $Id: parkbd.c,v 1.9 2002/01/22 20:44:10 vojtech Exp $
*
* Copyright (c) 1999-2001 Vojtech Pavlik
*/
/*
* Parallel port to Keyboard port adapter 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 <vo...@uc...>, or by paper mail:
* Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic
*/
#include <linux/module.h>
#include <linux/parport.h>
#include <linux/init.h>
#include <linux/serio.h>
MODULE_AUTHOR("Vojtech Pavlik <vo...@uc...>");
MODULE_DESCRIPTION("Parallel port to Keyboard port adapter driver");
MODULE_LICENSE("GPL");
MODULE_PARM(parkbd, "1i");
MODULE_PARM(parkbd_mode, "1i");
#define PARKBD_CLOCK 0x01 /* Strobe & Ack */
#define PARKBD_DATA 0x02 /* AutoFd & Busy */
static int parkbd = 0;
static int parkbd_mode = SERIO_8042;
static int parkbd_buffer = 0;
static int parkbd_counter = 0;
static int parkbd_last = 0;
static int parkbd_writing = 0;
static unsigned long parkbd_start = 0;
static struct pardevice *parkbd_dev;
static char parkbd_name[] = "PARKBD AT/XT keyboard adapter";
static char parkbd_phys[32];
static int parkbd_readlines(void)
{
return (parport_read_status(parkbd_dev->port) >> 6) ^ 2;
}
static void parkbd_writelines(int data)
{
parport_write_control(parkbd_dev->port, (~data & 3) | 0x10);
}
static int parkbd_write(struct serio *port, unsigned char c)
{
unsigned char p;
if (!parkbd_mode) return -1;
p = c ^ (c >> 4);
p = p ^ (p >> 2);
p = p ^ (p >> 1);
parkbd_counter = 0;
parkbd_writing = 1;
parkbd_buffer = c | (((int) (~p & 1)) << 8) | 0x600;
parkbd_writelines(2);
return 0;
}
static int parkbd_open(struct serio *port)
{
return 0;
}
static void parkbd_close(struct serio *port)
{
}
static struct serio parkbd_port =
{
write: parkbd_write,
open: parkbd_open,
close: parkbd_close,
name: parkbd_name,
phys: parkbd_phys,
};
static void parkbd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
if (parkbd_writing) {
if (parkbd_counter && ((parkbd_counter == 11) || (jiffies - parkbd_last > 1))) {
parkbd_counter = 0;
parkbd_buffer = 0;
parkbd_writing = 0;
parkbd_writelines(3);
return;
}
parkbd_writelines(((parkbd_buffer >> parkbd_counter++) & 1) | 2);
if (parkbd_counter == 11) {
parkbd_counter = 0;
parkbd_buffer = 0;
parkbd_writing = 0;
parkbd_writelines(3);
}
} else {
if ((parkbd_counter == parkbd_mode + 10) || (jiffies - parkbd_last > 1)) {
parkbd_counter = 0;
parkbd_buffer = 0;
}
parkbd_buffer |= (parkbd_readlines() >> 1) << parkbd_counter++;
if (parkbd_counter == parkbd_mode + 10) {
if (parkbd_port.dev)
parkbd_port.dev->interrupt(&parkbd_port, (parkbd_buffer >> (2 - parkbd_mode)) & 0xff, 0);
}
}
parkbd_last = jiffies;
}
static int parkbd_getport(void)
{
struct parport *pp;
if (parkbd < 0) {
printk(KERN_ERR "parkbd: no port specified\n");
return -ENODEV;
}
for (pp = parport_enumerate(); pp != NULL && (parkbd > 0); pp = pp->next) parkbd--;
if (pp == NULL) {
printk(KERN_ERR "parkbd: no such parport\n");
return -ENODEV;
}
parkbd_dev = parport_register_device(pp, "parkbd", NULL, NULL, parkbd_interrupt, PARPORT_DEV_EXCL, NULL);
if (!parkbd_dev)
return -ENODEV;
if (parport_claim(parkbd_dev)) {
parport_unregister_device(parkbd_dev);
return -EBUSY;
}
parkbd_start = jiffies;
return 0;
}
int __init parkbd_init(void)
{
if (parkbd_getport()) return -1;
parkbd_writelines(3);
parkbd_port.type = parkbd_mode;
sprintf(parkbd_phys, "%s/serio0", parkbd_dev->port->name);
serio_register_port(&parkbd_port);
printk(KERN_INFO "serio: PARKBD %s adapter on %s\n",
parkbd_mode ? "AT" : "XT", parkbd_dev->port->name);
return 0;
}
void __exit parkbd_exit(void)
{
parport_release(parkbd_dev);
serio_unregister_port(&parkbd_port);
parport_unregister_device(parkbd_dev);
}
module_init(parkbd_init);
module_exit(parkbd_exit);
|