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); |