2005-04-17 02:20:36 +04:00
/*
* USB Wacom Graphire and Wacom Intuos tablet support
*
* Copyright ( c ) 2000 - 2004 Vojtech Pavlik < vojtech @ ucw . cz >
* Copyright ( c ) 2000 Andreas Bach Aaen < abach @ stofanet . dk >
* Copyright ( c ) 2000 Clifford Wolf < clifford @ clifford . at >
* Copyright ( c ) 2000 Sam Mosel < sam . mosel @ computer . org >
* Copyright ( c ) 2000 James E . Blair < corvus @ gnu . org >
* Copyright ( c ) 2000 Daniel Egger < egger @ suse . de >
* Copyright ( c ) 2001 Frederic Lepied < flepied @ mandrakesoft . com >
* Copyright ( c ) 2004 Panagiotis Issaris < panagiotis . issaris @ mech . kuleuven . ac . be >
2005-06-06 11:25:50 +04:00
* Copyright ( c ) 2002 - 2005 Ping Cheng < pingc @ wacom . com >
2005-04-17 02:20:36 +04:00
*
* 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 ,
2005-05-29 11:29:01 +04:00
* they belong in userspace
2005-04-17 02:20:36 +04:00
* 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 4 D 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 , 4 D 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 .
* v1 .21 .1 ( fl ) - added Graphire2 support
* v1 .21 .2 ( fl ) - added Intuos2 support
* - added all the PL ids
* v1 .21 .3 ( fl ) - added another eraser id from Neil Okamoto
* - added smooth filter for Graphire from Peri Hankey
* - added PenPartner support from Olaf van Es
* - new tool ids from Ole Martin Bjoerndalen
* v1 .29 ( pc ) - Add support for more tablets
* - Fix pressure reporting
* v1 .30 ( vp ) - Merge 2.4 and 2.5 drivers
* - Since 2.5 now has input_sync ( ) , remove MSC_SERIAL abuse
* - Cleanups here and there
* v1 .30 .1 ( pi ) - Added Graphire3 support
* v1 .40 ( pc ) - Add support for several new devices , fix eraser reporting , . . .
2005-06-06 11:25:50 +04:00
* v1 .43 ( pc ) - Added support for Cintiq 21U X
2005-11-17 20:46:51 +03:00
* - Fixed a Graphire bug
* - Merged wacom_intuos3_irq into wacom_intuos_irq
* v1 .44 ( pc ) - Added support for Graphire4 , Cintiq 710 , Intuos3 6 x11 , etc .
* - Report Device IDs
2005-04-17 02:20:36 +04:00
*/
/*
* 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 .
*/
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/input.h>
# include <linux/module.h>
# include <linux/init.h>
# include <linux/usb.h>
2005-06-30 09:49:08 +04:00
# include <linux/usb_input.h>
2005-04-17 02:20:36 +04:00
# include <asm/unaligned.h>
# include <asm/byteorder.h>
/*
* Version Information
*/
2005-11-17 20:46:51 +03:00
# define DRIVER_VERSION "v1.44"
2005-04-17 02:20:36 +04:00
# define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
# 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
2005-11-17 20:46:51 +03:00
# define STYLUS_DEVICE_ID 0x02
# define CURSOR_DEVICE_ID 0x06
# define ERASER_DEVICE_ID 0x0A
2005-04-17 02:20:36 +04:00
2005-06-06 11:25:50 +04:00
enum {
PENPARTNER = 0 ,
GRAPHIRE ,
2005-11-17 20:46:51 +03:00
G4 ,
2005-06-06 11:25:50 +04:00
PL ,
INTUOS ,
INTUOS3 ,
CINTIQ ,
MAX_TYPE
} ;
2005-04-17 02:20:36 +04:00
struct wacom_features {
char * name ;
int pktlen ;
int x_max ;
int y_max ;
int pressure_max ;
int distance_max ;
int type ;
usb_complete_t irq ;
} ;
struct wacom {
signed char * data ;
dma_addr_t data_dma ;
2005-09-15 11:01:47 +04:00
struct input_dev * dev ;
2005-04-17 02:20:36 +04:00
struct usb_device * usbdev ;
struct urb * irq ;
struct wacom_features * features ;
int tool [ 2 ] ;
2005-11-17 20:46:51 +03:00
int id [ 2 ] ;
2005-04-17 02:20:36 +04:00
__u32 serial [ 2 ] ;
char phys [ 32 ] ;
} ;
# define USB_REQ_SET_REPORT 0x09
static int usb_set_report ( struct usb_interface * intf , unsigned char type ,
unsigned char id , void * buf , int size )
{
return usb_control_msg ( interface_to_usbdev ( intf ) ,
usb_sndctrlpipe ( interface_to_usbdev ( intf ) , 0 ) ,
USB_REQ_SET_REPORT , USB_TYPE_CLASS | USB_RECIP_INTERFACE ,
( type < < 8 ) + id , intf - > altsetting [ 0 ] . desc . bInterfaceNumber ,
buf , size , 1000 ) ;
}
static void wacom_pl_irq ( struct urb * urb , struct pt_regs * regs )
{
struct wacom * wacom = urb - > context ;
unsigned char * data = wacom - > data ;
2005-09-15 11:01:47 +04:00
struct input_dev * dev = wacom - > dev ;
2005-11-17 20:46:51 +03:00
int prox , pressure , id ;
2005-04-17 02:20:36 +04:00
int retval ;
switch ( urb - > status ) {
case 0 :
/* success */
break ;
case - ECONNRESET :
case - ENOENT :
case - ESHUTDOWN :
/* this urb is terminated, clean up */
dbg ( " %s - urb shutting down with status: %d " , __FUNCTION__ , urb - > status ) ;
return ;
default :
dbg ( " %s - nonzero urb status received: %d " , __FUNCTION__ , urb - > status ) ;
goto exit ;
}
if ( data [ 0 ] ! = 2 ) {
dbg ( " wacom_pl_irq: received unknown report #%d " , data [ 0 ] ) ;
goto exit ;
}
prox = data [ 1 ] & 0x40 ;
input_regs ( dev , regs ) ;
2005-05-29 11:29:01 +04:00
2005-11-17 20:46:51 +03:00
id = ERASER_DEVICE_ID ;
2005-04-17 02:20:36 +04:00
if ( prox ) {
pressure = ( signed char ) ( ( data [ 7 ] < < 1 ) | ( ( data [ 4 ] > > 2 ) & 1 ) ) ;
if ( wacom - > features - > pressure_max > 255 )
pressure = ( pressure < < 1 ) | ( ( data [ 4 ] > > 6 ) & 1 ) ;
pressure + = ( wacom - > features - > pressure_max + 1 ) / 2 ;
/*
* if going from out of proximity into proximity select between the eraser
* and the pen based on the state of the stylus2 button , choose eraser if
* pressed else choose pen . if not a proximity change from out to in , send
* an out of proximity for previous tool then a in for new tool .
*/
if ( ! wacom - > tool [ 0 ] ) {
2005-11-17 20:46:51 +03:00
/* Eraser bit set for DTF */
if ( data [ 1 ] & 0x10 )
wacom - > tool [ 1 ] = BTN_TOOL_RUBBER ;
else
/* Going into proximity select tool */
wacom - > tool [ 1 ] = ( data [ 4 ] & 0x20 ) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN ;
2005-06-06 11:28:29 +04:00
} else {
2005-04-17 02:20:36 +04:00
/* was entered with stylus2 pressed */
2005-11-17 20:46:51 +03:00
if ( wacom - > tool [ 1 ] = = BTN_TOOL_RUBBER & & ! ( data [ 4 ] & 0x20 ) ) {
2005-04-17 02:20:36 +04:00
/* report out proximity for previous tool */
input_report_key ( dev , wacom - > tool [ 1 ] , 0 ) ;
input_sync ( dev ) ;
wacom - > tool [ 1 ] = BTN_TOOL_PEN ;
goto exit ;
}
}
if ( wacom - > tool [ 1 ] ! = BTN_TOOL_RUBBER ) {
/* Unknown tool selected default to pen tool */
wacom - > tool [ 1 ] = BTN_TOOL_PEN ;
2005-11-17 20:46:51 +03:00
id = STYLUS_DEVICE_ID ;
2005-04-17 02:20:36 +04:00
}
2005-11-17 20:46:51 +03:00
input_report_key ( dev , wacom - > tool [ 1 ] , id ) ; /* report in proximity for tool */
2005-06-06 11:25:50 +04:00
input_report_abs ( dev , ABS_X , data [ 3 ] | ( data [ 2 ] < < 7 ) | ( ( data [ 1 ] & 0x03 ) < < 14 ) ) ;
input_report_abs ( dev , ABS_Y , data [ 6 ] | ( data [ 5 ] < < 7 ) | ( ( data [ 4 ] & 0x03 ) < < 14 ) ) ;
2005-04-17 02:20:36 +04:00
input_report_abs ( dev , ABS_PRESSURE , pressure ) ;
input_report_key ( dev , BTN_TOUCH , data [ 4 ] & 0x08 ) ;
input_report_key ( dev , BTN_STYLUS , data [ 4 ] & 0x10 ) ;
/* Only allow the stylus2 button to be reported for the pen tool. */
input_report_key ( dev , BTN_STYLUS2 , ( wacom - > tool [ 1 ] = = BTN_TOOL_PEN ) & & ( data [ 4 ] & 0x20 ) ) ;
2005-06-06 11:28:29 +04:00
} else {
2005-04-17 02:20:36 +04:00
/* report proximity-out of a (valid) tool */
if ( wacom - > tool [ 1 ] ! = BTN_TOOL_RUBBER ) {
/* Unknown tool selected default to pen tool */
wacom - > tool [ 1 ] = BTN_TOOL_PEN ;
}
input_report_key ( dev , wacom - > tool [ 1 ] , prox ) ;
}
wacom - > tool [ 0 ] = prox ; /* Save proximity state */
input_sync ( dev ) ;
2005-06-06 11:28:29 +04:00
exit :
2005-04-17 02:20:36 +04:00
retval = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( retval )
err ( " %s - usb_submit_urb failed with result %d " ,
__FUNCTION__ , retval ) ;
}
static void wacom_ptu_irq ( struct urb * urb , struct pt_regs * regs )
{
struct wacom * wacom = urb - > context ;
unsigned char * data = wacom - > data ;
2005-09-15 11:01:47 +04:00
struct input_dev * dev = wacom - > dev ;
2005-04-17 02:20:36 +04:00
int retval ;
switch ( urb - > status ) {
case 0 :
/* success */
break ;
case - ECONNRESET :
case - ENOENT :
case - ESHUTDOWN :
/* this urb is terminated, clean up */
dbg ( " %s - urb shutting down with status: %d " , __FUNCTION__ , urb - > status ) ;
return ;
default :
dbg ( " %s - nonzero urb status received: %d " , __FUNCTION__ , urb - > status ) ;
goto exit ;
}
2005-06-06 11:28:29 +04:00
if ( data [ 0 ] ! = 2 ) {
2005-04-17 02:20:36 +04:00
printk ( KERN_INFO " wacom_ptu_irq: received unknown report #%d \n " , data [ 0 ] ) ;
goto exit ;
}
input_regs ( dev , regs ) ;
2005-06-06 11:28:29 +04:00
if ( data [ 1 ] & 0x04 ) {
2005-11-17 20:46:51 +03:00
input_report_key ( dev , BTN_TOOL_RUBBER , ( data [ 1 ] & 0x20 ) ? ERASER_DEVICE_ID : 0 ) ;
2005-04-17 02:20:36 +04:00
input_report_key ( dev , BTN_TOUCH , data [ 1 ] & 0x08 ) ;
2005-06-06 11:28:29 +04:00
} else {
2005-11-17 20:46:51 +03:00
input_report_key ( dev , BTN_TOOL_PEN , ( data [ 1 ] & 0x20 ) ? STYLUS_DEVICE_ID : 0 ) ;
2005-04-17 02:20:36 +04:00
input_report_key ( dev , BTN_TOUCH , data [ 1 ] & 0x01 ) ;
}
input_report_abs ( dev , ABS_X , le16_to_cpu ( * ( __le16 * ) & data [ 2 ] ) ) ;
input_report_abs ( dev , ABS_Y , le16_to_cpu ( * ( __le16 * ) & data [ 4 ] ) ) ;
input_report_abs ( dev , ABS_PRESSURE , le16_to_cpu ( * ( __le16 * ) & data [ 6 ] ) ) ;
input_report_key ( dev , BTN_STYLUS , data [ 1 ] & 0x02 ) ;
input_report_key ( dev , BTN_STYLUS2 , data [ 1 ] & 0x10 ) ;
input_sync ( dev ) ;
2005-06-06 11:28:29 +04:00
exit :
2005-04-17 02:20:36 +04:00
retval = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( retval )
err ( " %s - usb_submit_urb failed with result %d " ,
__FUNCTION__ , retval ) ;
}
static void wacom_penpartner_irq ( struct urb * urb , struct pt_regs * regs )
{
struct wacom * wacom = urb - > context ;
unsigned char * data = wacom - > data ;
2005-09-15 11:01:47 +04:00
struct input_dev * dev = wacom - > dev ;
2005-04-17 02:20:36 +04:00
int retval ;
switch ( urb - > status ) {
case 0 :
/* success */
break ;
case - ECONNRESET :
case - ENOENT :
case - ESHUTDOWN :
/* this urb is terminated, clean up */
dbg ( " %s - urb shutting down with status: %d " , __FUNCTION__ , urb - > status ) ;
return ;
default :
dbg ( " %s - nonzero urb status received: %d " , __FUNCTION__ , urb - > status ) ;
goto exit ;
}
if ( data [ 0 ] ! = 2 ) {
printk ( KERN_INFO " wacom_penpartner_irq: received unknown report #%d \n " , data [ 0 ] ) ;
goto exit ;
}
input_regs ( dev , regs ) ;
2005-11-17 20:46:51 +03:00
input_report_key ( dev , BTN_TOOL_PEN , STYLUS_DEVICE_ID ) ;
2005-04-17 02:20:36 +04:00
input_report_abs ( dev , ABS_X , le16_to_cpu ( * ( __le16 * ) & data [ 1 ] ) ) ;
input_report_abs ( dev , ABS_Y , le16_to_cpu ( * ( __le16 * ) & data [ 3 ] ) ) ;
input_report_abs ( dev , ABS_PRESSURE , ( signed char ) data [ 6 ] + 127 ) ;
input_report_key ( dev , BTN_TOUCH , ( ( signed char ) data [ 6 ] > - 80 ) & & ! ( data [ 5 ] & 0x20 ) ) ;
input_report_key ( dev , BTN_STYLUS , ( data [ 5 ] & 0x40 ) ) ;
input_sync ( dev ) ;
2005-06-06 11:28:29 +04:00
exit :
2005-04-17 02:20:36 +04:00
retval = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( retval )
err ( " %s - usb_submit_urb failed with result %d " ,
__FUNCTION__ , retval ) ;
}
static void wacom_graphire_irq ( struct urb * urb , struct pt_regs * regs )
{
struct wacom * wacom = urb - > context ;
unsigned char * data = wacom - > data ;
2005-09-15 11:01:47 +04:00
struct input_dev * dev = wacom - > dev ;
2005-11-17 20:46:51 +03:00
int x , y , id , rw ;
2005-04-17 02:20:36 +04:00
int retval ;
switch ( urb - > status ) {
case 0 :
/* success */
break ;
case - ECONNRESET :
case - ENOENT :
case - ESHUTDOWN :
/* this urb is terminated, clean up */
dbg ( " %s - urb shutting down with status: %d " , __FUNCTION__ , urb - > status ) ;
return ;
default :
dbg ( " %s - nonzero urb status received: %d " , __FUNCTION__ , urb - > status ) ;
goto exit ;
}
if ( data [ 0 ] ! = 2 ) {
dbg ( " wacom_graphire_irq: received unknown report #%d " , data [ 0 ] ) ;
goto exit ;
}
input_regs ( dev , regs ) ;
2005-11-17 20:46:51 +03:00
id = STYLUS_DEVICE_ID ;
2005-06-06 11:28:29 +04:00
if ( data [ 1 ] & 0x10 ) { /* in prox */
2005-06-06 11:25:50 +04:00
switch ( ( data [ 1 ] > > 5 ) & 3 ) {
2005-04-17 02:20:36 +04:00
2005-06-06 11:25:50 +04:00
case 0 : /* Pen */
wacom - > tool [ 0 ] = BTN_TOOL_PEN ;
break ;
2005-04-17 02:20:36 +04:00
2005-06-06 11:25:50 +04:00
case 1 : /* Rubber */
wacom - > tool [ 0 ] = BTN_TOOL_RUBBER ;
2005-11-17 20:46:51 +03:00
id = ERASER_DEVICE_ID ;
2005-06-06 11:25:50 +04:00
break ;
2005-04-17 02:20:36 +04:00
2005-06-06 11:25:50 +04:00
case 2 : /* Mouse with wheel */
input_report_key ( dev , BTN_MIDDLE , data [ 1 ] & 0x04 ) ;
2005-11-17 20:46:51 +03:00
if ( wacom - > features - > type = = G4 ) {
rw = data [ 7 ] & 0x04 ? - ( data [ 7 ] & 0x03 ) : ( data [ 7 ] & 0x03 ) ;
input_report_rel ( dev , REL_WHEEL , rw ) ;
} else
input_report_rel ( dev , REL_WHEEL , ( signed char ) data [ 6 ] ) ;
2005-06-06 11:25:50 +04:00
/* fall through */
2005-04-17 02:20:36 +04:00
2005-06-06 11:28:29 +04:00
case 3 : /* Mouse without wheel */
2005-06-06 11:25:50 +04:00
wacom - > tool [ 0 ] = BTN_TOOL_MOUSE ;
2005-11-17 20:46:51 +03:00
id = CURSOR_DEVICE_ID ;
2005-06-06 11:25:50 +04:00
input_report_key ( dev , BTN_LEFT , data [ 1 ] & 0x01 ) ;
input_report_key ( dev , BTN_RIGHT , data [ 1 ] & 0x02 ) ;
2005-11-17 20:46:51 +03:00
if ( wacom - > features - > type = = G4 )
input_report_abs ( dev , ABS_DISTANCE , data [ 6 ] ) ;
else
input_report_abs ( dev , ABS_DISTANCE , data [ 7 ] ) ;
2005-06-06 11:25:50 +04:00
break ;
}
2005-04-17 02:20:36 +04:00
}
2005-08-17 02:16:32 +04:00
if ( data [ 1 ] & 0x90 ) {
x = le16_to_cpu ( * ( __le16 * ) & data [ 2 ] ) ;
y = le16_to_cpu ( * ( __le16 * ) & data [ 4 ] ) ;
2005-04-17 02:20:36 +04:00
input_report_abs ( dev , ABS_X , x ) ;
input_report_abs ( dev , ABS_Y , y ) ;
2005-08-17 02:16:32 +04:00
if ( wacom - > tool [ 0 ] ! = BTN_TOOL_MOUSE ) {
2005-11-17 20:46:51 +03:00
input_report_abs ( dev , ABS_PRESSURE , data [ 6 ] | ( ( data [ 7 ] & 0x01 ) < < 8 ) ) ;
2005-08-17 02:16:32 +04:00
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 ) ;
}
2005-06-06 11:25:50 +04:00
}
2005-04-17 02:20:36 +04:00
2005-11-17 20:46:51 +03:00
input_report_key ( dev , wacom - > tool [ 0 ] , ( data [ 1 ] & 0x10 ) ? id : 0 ) ;
2005-04-17 02:20:36 +04:00
input_sync ( dev ) ;
2005-11-17 20:46:51 +03:00
/* send pad data */
if ( wacom - > features - > type = = G4 ) {
/* fist time sending pad data */
if ( wacom - > tool [ 1 ] ! = BTN_TOOL_FINGER ) {
wacom - > id [ 1 ] = 0 ;
wacom - > serial [ 1 ] = ( data [ 7 ] & 0x38 ) > > 2 ;
}
if ( data [ 7 ] & 0xf8 ) {
input_report_key ( dev , BTN_0 , ( data [ 7 ] & 0x40 ) ) ;
input_report_key ( dev , BTN_4 , ( data [ 7 ] & 0x80 ) ) ;
if ( ( ( data [ 7 ] & 0x38 ) > > 2 ) = = ( wacom - > serial [ 1 ] & 0x0e ) )
/* alter REL_WHEEL value so X apps can get it */
wacom - > serial [ 1 ] + = ( wacom - > serial [ 1 ] & 0x01 ) ? - 1 : 1 ;
else
wacom - > serial [ 1 ] = ( data [ 7 ] & 0x38 ) > > 2 ;
/* don't alter the value when there is no wheel event */
if ( wacom - > serial [ 1 ] = = 1 )
wacom - > serial [ 1 ] = 0 ;
rw = wacom - > serial [ 1 ] ;
rw = ( rw & 0x08 ) ? - ( rw & 0x07 ) : ( rw & 0x07 ) ;
input_report_rel ( dev , REL_WHEEL , rw ) ;
wacom - > tool [ 1 ] = BTN_TOOL_FINGER ;
wacom - > id [ 1 ] = data [ 7 ] & 0xf8 ;
input_report_key ( dev , wacom - > tool [ 1 ] , 0xf0 ) ;
input_event ( dev , EV_MSC , MSC_SERIAL , 0xf0 ) ;
} else if ( wacom - > id [ 1 ] ) {
wacom - > id [ 1 ] = 0 ;
wacom - > serial [ 1 ] = 0 ;
input_report_key ( dev , wacom - > tool [ 1 ] , 0 ) ;
input_event ( dev , EV_MSC , MSC_SERIAL , 0xf0 ) ;
}
input_sync ( dev ) ;
}
2005-06-06 11:28:29 +04:00
exit :
2005-04-17 02:20:36 +04:00
retval = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( retval )
err ( " %s - usb_submit_urb failed with result %d " ,
__FUNCTION__ , retval ) ;
}
static int wacom_intuos_inout ( struct urb * urb )
{
struct wacom * wacom = urb - > context ;
unsigned char * data = wacom - > data ;
2005-09-15 11:01:47 +04:00
struct input_dev * dev = wacom - > dev ;
2005-04-17 02:20:36 +04:00
int idx ;
/* tool number */
idx = data [ 1 ] & 0x01 ;
/* Enter report */
2005-06-06 11:28:29 +04:00
if ( ( data [ 1 ] & 0xfc ) = = 0xc0 ) {
2005-04-17 02:20:36 +04:00
/* serial number of the tool */
2005-06-06 11:25:50 +04:00
wacom - > serial [ idx ] = ( ( data [ 3 ] & 0x0f ) < < 28 ) +
( data [ 4 ] < < 20 ) + ( data [ 5 ] < < 12 ) +
( data [ 6 ] < < 4 ) + ( data [ 7 ] > > 4 ) ;
2005-04-17 02:20:36 +04:00
2005-11-17 20:46:51 +03:00
wacom - > id [ idx ] = ( data [ 2 ] < < 4 ) | ( data [ 3 ] > > 4 ) ;
switch ( wacom - > id [ idx ] ) {
2005-04-17 02:20:36 +04:00
case 0x812 : /* Inking pen */
case 0x801 : /* Intuos3 Inking pen */
case 0x012 :
wacom - > tool [ idx ] = BTN_TOOL_PENCIL ;
break ;
case 0x822 : /* Pen */
case 0x842 :
case 0x852 :
case 0x823 : /* Intuos3 Grip Pen */
case 0x813 : /* Intuos3 Classic Pen */
case 0x885 : /* Intuos3 Marker Pen */
case 0x022 :
wacom - > tool [ idx ] = BTN_TOOL_PEN ;
break ;
case 0x832 : /* Stroke pen */
case 0x032 :
wacom - > tool [ idx ] = BTN_TOOL_BRUSH ;
break ;
case 0x007 : /* Mouse 4D and 2D */
case 0x09c :
case 0x094 :
case 0x017 : /* Intuos3 2D Mouse */
wacom - > tool [ idx ] = BTN_TOOL_MOUSE ;
break ;
case 0x096 : /* Lens cursor */
case 0x097 : /* Intuos3 Lens cursor */
wacom - > tool [ idx ] = BTN_TOOL_LENS ;
break ;
case 0x82a : /* Eraser */
case 0x85a :
case 0x91a :
case 0xd1a :
case 0x0fa :
case 0x82b : /* Intuos3 Grip Pen Eraser */
case 0x81b : /* Intuos3 Classic Pen Eraser */
case 0x91b : /* Intuos3 Airbrush Eraser */
wacom - > tool [ idx ] = BTN_TOOL_RUBBER ;
break ;
case 0xd12 :
case 0x912 :
case 0x112 :
case 0x913 : /* Intuos3 Airbrush */
wacom - > tool [ idx ] = BTN_TOOL_AIRBRUSH ;
2005-06-06 11:25:50 +04:00
break ;
2005-04-17 02:20:36 +04:00
default : /* Unknown tool */
wacom - > tool [ idx ] = BTN_TOOL_PEN ;
}
2005-11-17 20:46:51 +03:00
input_report_key ( dev , wacom - > tool [ idx ] , wacom - > id [ idx ] ) ;
2005-04-17 02:20:36 +04:00
input_event ( dev , EV_MSC , MSC_SERIAL , wacom - > serial [ idx ] ) ;
input_sync ( dev ) ;
return 1 ;
}
/* Exit report */
if ( ( data [ 1 ] & 0xfe ) = = 0x80 ) {
input_report_key ( dev , wacom - > tool [ idx ] , 0 ) ;
input_event ( dev , EV_MSC , MSC_SERIAL , wacom - > serial [ idx ] ) ;
input_sync ( dev ) ;
return 1 ;
}
return 0 ;
}
static void wacom_intuos_general ( struct urb * urb )
{
struct wacom * wacom = urb - > context ;
unsigned char * data = wacom - > data ;
2005-09-15 11:01:47 +04:00
struct input_dev * dev = wacom - > dev ;
2005-04-17 02:20:36 +04:00
unsigned int t ;
/* general pen packet */
2005-06-06 11:28:29 +04:00
if ( ( data [ 1 ] & 0xb8 ) = = 0xa0 ) {
2005-06-06 11:25:50 +04:00
t = ( data [ 6 ] < < 2 ) | ( ( data [ 7 ] > > 6 ) & 3 ) ;
2005-04-17 02:20:36 +04:00
input_report_abs ( dev , ABS_PRESSURE , t ) ;
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 ) ;
}
/* airbrush second packet */
2005-06-06 11:28:29 +04:00
if ( ( data [ 1 ] & 0xbc ) = = 0xb4 ) {
2005-04-17 02:20:36 +04:00
input_report_abs ( dev , ABS_WHEEL ,
2005-06-06 11:25:50 +04:00
( data [ 6 ] < < 2 ) | ( ( data [ 7 ] > > 6 ) & 3 ) ) ;
2005-04-17 02:20:36 +04:00
input_report_abs ( dev , ABS_TILT_X ,
( ( data [ 7 ] < < 1 ) & 0x7e ) | ( data [ 8 ] > > 7 ) ) ;
input_report_abs ( dev , ABS_TILT_Y , data [ 8 ] & 0x7f ) ;
}
return ;
}
static void wacom_intuos_irq ( struct urb * urb , struct pt_regs * regs )
{
struct wacom * wacom = urb - > context ;
unsigned char * data = wacom - > data ;
2005-09-15 11:01:47 +04:00
struct input_dev * dev = wacom - > dev ;
2005-04-17 02:20:36 +04:00
unsigned int t ;
int idx ;
int retval ;
switch ( urb - > status ) {
case 0 :
/* success */
break ;
case - ECONNRESET :
case - ENOENT :
case - ESHUTDOWN :
/* this urb is terminated, clean up */
dbg ( " %s - urb shutting down with status: %d " , __FUNCTION__ , urb - > status ) ;
return ;
default :
dbg ( " %s - nonzero urb status received: %d " , __FUNCTION__ , urb - > status ) ;
goto exit ;
}
2005-06-06 11:25:50 +04:00
if ( data [ 0 ] ! = 2 & & data [ 0 ] ! = 5 & & data [ 0 ] ! = 6 & & data [ 0 ] ! = 12 ) {
2005-04-17 02:20:36 +04:00
dbg ( " wacom_intuos_irq: received unknown report #%d " , data [ 0 ] ) ;
goto exit ;
}
input_regs ( dev , regs ) ;
/* tool number */
idx = data [ 1 ] & 0x01 ;
/* pad packets. Works as a second tool and is always in prox */
2005-06-06 11:28:29 +04:00
if ( data [ 0 ] = = 12 ) {
2005-04-17 02:20:36 +04:00
/* initiate the pad as a device */
2005-06-06 11:28:29 +04:00
if ( wacom - > tool [ 1 ] ! = BTN_TOOL_FINGER ) {
2005-04-17 02:20:36 +04:00
wacom - > tool [ 1 ] = BTN_TOOL_FINGER ;
input_report_key ( dev , wacom - > tool [ 1 ] , 1 ) ;
}
input_report_key ( dev , BTN_0 , ( data [ 5 ] & 0x01 ) ) ;
input_report_key ( dev , BTN_1 , ( data [ 5 ] & 0x02 ) ) ;
input_report_key ( dev , BTN_2 , ( data [ 5 ] & 0x04 ) ) ;
input_report_key ( dev , BTN_3 , ( data [ 5 ] & 0x08 ) ) ;
input_report_key ( dev , BTN_4 , ( data [ 6 ] & 0x01 ) ) ;
input_report_key ( dev , BTN_5 , ( data [ 6 ] & 0x02 ) ) ;
input_report_key ( dev , BTN_6 , ( data [ 6 ] & 0x04 ) ) ;
input_report_key ( dev , BTN_7 , ( data [ 6 ] & 0x08 ) ) ;
input_report_abs ( dev , ABS_RX , ( ( data [ 1 ] & 0x1f ) < < 8 ) | data [ 2 ] ) ;
input_report_abs ( dev , ABS_RY , ( ( data [ 3 ] & 0x1f ) < < 8 ) | data [ 4 ] ) ;
input_event ( dev , EV_MSC , MSC_SERIAL , 0xffffffff ) ;
input_sync ( dev ) ;
goto exit ;
}
/* process in/out prox events */
2005-06-06 11:28:29 +04:00
if ( wacom_intuos_inout ( urb ) )
goto exit ;
2005-04-17 02:20:36 +04:00
2005-06-06 11:25:50 +04:00
/* Cintiq doesn't send data when RDY bit isn't set */
2005-06-06 11:28:29 +04:00
if ( ( wacom - > features - > type = = CINTIQ ) & & ! ( data [ 1 ] & 0x40 ) )
2005-08-17 02:16:32 +04:00
goto exit ;
2005-06-06 11:25:50 +04:00
2005-06-06 11:28:29 +04:00
if ( wacom - > features - > type > = INTUOS3 ) {
2005-06-06 11:25:50 +04:00
input_report_abs ( dev , ABS_X , ( data [ 2 ] < < 9 ) | ( data [ 3 ] < < 1 ) | ( ( data [ 9 ] > > 1 ) & 1 ) ) ;
input_report_abs ( dev , ABS_Y , ( data [ 4 ] < < 9 ) | ( data [ 5 ] < < 1 ) | ( data [ 9 ] & 1 ) ) ;
input_report_abs ( dev , ABS_DISTANCE , ( ( data [ 9 ] > > 2 ) & 0x3f ) ) ;
2005-06-06 11:28:29 +04:00
} else {
2005-06-06 11:25:50 +04:00
input_report_abs ( dev , ABS_X , be16_to_cpu ( * ( __be16 * ) & data [ 2 ] ) ) ;
input_report_abs ( dev , ABS_Y , be16_to_cpu ( * ( __be16 * ) & data [ 4 ] ) ) ;
input_report_abs ( dev , ABS_DISTANCE , ( ( data [ 9 ] > > 3 ) & 0x1f ) ) ;
}
2005-04-17 02:20:36 +04:00
/* process general packets */
wacom_intuos_general ( urb ) ;
2005-06-06 11:25:50 +04:00
/* 4D mouse, 2D mouse, marker pen rotation, or Lens cursor packets */
if ( ( data [ 1 ] & 0xbc ) = = 0xa8 | | ( data [ 1 ] & 0xbe ) = = 0xb0 ) {
2005-06-06 11:28:29 +04:00
if ( data [ 1 ] & 0x02 ) {
/* Rotation packet */
if ( wacom - > features - > type > = INTUOS3 ) {
2005-06-06 11:25:50 +04:00
/* I3 marker pen rotation reported as wheel
* due to valuator limitation
*/
t = ( data [ 6 ] < < 3 ) | ( ( data [ 7 ] > > 5 ) & 7 ) ;
t = ( data [ 7 ] & 0x20 ) ? ( ( t > 900 ) ? ( ( t - 1 ) / 2 - 1350 ) :
( ( t - 1 ) / 2 + 450 ) ) : ( 450 - t / 2 ) ;
input_report_abs ( dev , ABS_WHEEL , t ) ;
2005-06-06 11:28:29 +04:00
} else {
2005-06-06 11:25:50 +04:00
/* 4D mouse rotation packet */
t = ( data [ 6 ] < < 3 ) | ( ( data [ 7 ] > > 5 ) & 7 ) ;
input_report_abs ( dev , ABS_RZ , ( data [ 7 ] & 0x20 ) ?
( ( t - 1 ) / 2 ) : - t / 2 ) ;
}
2005-06-06 11:28:29 +04:00
} else if ( ! ( data [ 1 ] & 0x10 ) & & wacom - > features - > type < INTUOS3 ) {
/* 4D mouse packet */
2005-06-06 11:25:50 +04:00
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 ) ;
input_report_key ( dev , BTN_SIDE , data [ 8 ] & 0x20 ) ;
input_report_key ( dev , BTN_EXTRA , data [ 8 ] & 0x10 ) ;
t = ( data [ 6 ] < < 2 ) | ( ( data [ 7 ] > > 6 ) & 3 ) ;
input_report_abs ( dev , ABS_THROTTLE , ( data [ 8 ] & 0x08 ) ? - t : t ) ;
2005-06-06 11:28:29 +04:00
} else if ( wacom - > tool [ idx ] = = BTN_TOOL_MOUSE ) {
/* 2D mouse packet */
2005-04-17 02:20:36 +04:00
input_report_key ( dev , BTN_LEFT , data [ 8 ] & 0x04 ) ;
input_report_key ( dev , BTN_MIDDLE , data [ 8 ] & 0x08 ) ;
input_report_key ( dev , BTN_RIGHT , data [ 8 ] & 0x10 ) ;
2005-06-06 11:25:50 +04:00
input_report_rel ( dev , REL_WHEEL , ( ( data [ 8 ] & 0x02 ) > > 1 )
2005-06-06 11:28:29 +04:00
- ( data [ 8 ] & 0x01 ) ) ;
2005-06-06 11:25:50 +04:00
/* I3 2D mouse side buttons */
2005-06-06 11:28:29 +04:00
if ( wacom - > features - > type = = INTUOS3 ) {
2005-06-06 11:25:50 +04:00
input_report_key ( dev , BTN_SIDE , data [ 8 ] & 0x40 ) ;
input_report_key ( dev , BTN_EXTRA , data [ 8 ] & 0x20 ) ;
}
2005-06-06 11:28:29 +04:00
} else if ( wacom - > features - > type < INTUOS3 ) {
/* Lens cursor packets */
2005-06-06 11:25:50 +04:00
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 ) ;
input_report_key ( dev , BTN_SIDE , data [ 8 ] & 0x10 ) ;
input_report_key ( dev , BTN_EXTRA , data [ 8 ] & 0x08 ) ;
2005-04-17 02:20:36 +04:00
}
}
2005-11-17 20:46:51 +03:00
input_report_key ( dev , wacom - > tool [ idx ] , wacom - > id [ idx ] ) ;
2005-04-17 02:20:36 +04:00
input_event ( dev , EV_MSC , MSC_SERIAL , wacom - > serial [ idx ] ) ;
input_sync ( dev ) ;
exit :
retval = usb_submit_urb ( urb , GFP_ATOMIC ) ;
if ( retval )
err ( " %s - usb_submit_urb failed with result %d " ,
__FUNCTION__ , retval ) ;
}
static struct wacom_features wacom_features [ ] = {
2005-06-06 11:28:29 +04:00
{ " Wacom Penpartner " , 7 , 5040 , 3780 , 255 , 32 , PENPARTNER , wacom_penpartner_irq } ,
2005-06-06 11:25:50 +04:00
{ " Wacom Graphire " , 8 , 10206 , 7422 , 511 , 32 , GRAPHIRE , wacom_graphire_irq } ,
{ " Wacom Graphire2 4x5 " , 8 , 10206 , 7422 , 511 , 32 , GRAPHIRE , wacom_graphire_irq } ,
2005-06-06 11:28:29 +04:00
{ " Wacom Graphire2 5x7 " , 8 , 13918 , 10206 , 511 , 32 , GRAPHIRE , wacom_graphire_irq } ,
2005-06-06 11:25:50 +04:00
{ " Wacom Graphire3 " , 8 , 10208 , 7424 , 511 , 32 , GRAPHIRE , wacom_graphire_irq } ,
{ " Wacom Graphire3 6x8 " , 8 , 16704 , 12064 , 511 , 32 , GRAPHIRE , wacom_graphire_irq } ,
2005-11-17 20:46:51 +03:00
{ " Wacom Graphire4 4x5 " , 8 , 10208 , 7424 , 511 , 32 , G4 , wacom_graphire_irq } ,
{ " Wacom Graphire4 6x8 " , 8 , 16704 , 12064 , 511 , 32 , G4 , wacom_graphire_irq } ,
{ " Wacom Volito " , 8 , 5104 , 3712 , 511 , 32 , GRAPHIRE , wacom_graphire_irq } ,
{ " Wacom PenStation2 " , 8 , 3250 , 2320 , 255 , 32 , GRAPHIRE , wacom_graphire_irq } ,
{ " Wacom Volito2 4x5 " , 8 , 5104 , 3712 , 511 , 32 , GRAPHIRE , wacom_graphire_irq } ,
{ " Wacom Volito2 2x3 " , 8 , 3248 , 2320 , 511 , 32 , GRAPHIRE , wacom_graphire_irq } ,
{ " Wacom PenPartner2 " , 8 , 3250 , 2320 , 255 , 32 , GRAPHIRE , wacom_graphire_irq } ,
2005-06-06 11:28:29 +04:00
{ " Wacom Intuos 4x5 " , 10 , 12700 , 10600 , 1023 , 15 , INTUOS , wacom_intuos_irq } ,
{ " Wacom Intuos 6x8 " , 10 , 20320 , 16240 , 1023 , 15 , INTUOS , wacom_intuos_irq } ,
{ " Wacom Intuos 9x12 " , 10 , 30480 , 24060 , 1023 , 15 , INTUOS , wacom_intuos_irq } ,
{ " Wacom Intuos 12x12 " , 10 , 30480 , 31680 , 1023 , 15 , INTUOS , wacom_intuos_irq } ,
{ " Wacom Intuos 12x18 " , 10 , 45720 , 31680 , 1023 , 15 , INTUOS , wacom_intuos_irq } ,
{ " Wacom PL400 " , 8 , 5408 , 4056 , 255 , 32 , PL , wacom_pl_irq } ,
{ " Wacom PL500 " , 8 , 6144 , 4608 , 255 , 32 , PL , wacom_pl_irq } ,
{ " Wacom PL600 " , 8 , 6126 , 4604 , 255 , 32 , PL , wacom_pl_irq } ,
{ " Wacom PL600SX " , 8 , 6260 , 5016 , 255 , 32 , PL , wacom_pl_irq } ,
{ " Wacom PL550 " , 8 , 6144 , 4608 , 511 , 32 , PL , wacom_pl_irq } ,
{ " Wacom PL800 " , 8 , 7220 , 5780 , 511 , 32 , PL , wacom_pl_irq } ,
2005-11-17 20:46:51 +03:00
{ " Wacom PL700 " , 8 , 6758 , 5406 , 511 , 32 , PL , wacom_pl_irq } ,
{ " Wacom PL510 " , 8 , 6282 , 4762 , 511 , 32 , PL , wacom_pl_irq } ,
{ " Wacom PL710 " , 8 , 34080 , 27660 , 511 , 32 , PL , wacom_pl_irq } ,
{ " Wacom DTF720 " , 8 , 6858 , 5506 , 511 , 32 , PL , wacom_pl_irq } ,
{ " Wacom Cintiq Partner " , 8 , 20480 , 15360 , 511 , 32 , PL , wacom_ptu_irq } ,
2005-06-06 11:25:50 +04:00
{ " Wacom Intuos2 4x5 " , 10 , 12700 , 10600 , 1023 , 15 , INTUOS , wacom_intuos_irq } ,
{ " Wacom Intuos2 6x8 " , 10 , 20320 , 16240 , 1023 , 15 , INTUOS , wacom_intuos_irq } ,
{ " Wacom Intuos2 9x12 " , 10 , 30480 , 24060 , 1023 , 15 , INTUOS , wacom_intuos_irq } ,
{ " Wacom Intuos2 12x12 " , 10 , 30480 , 31680 , 1023 , 15 , INTUOS , wacom_intuos_irq } ,
{ " Wacom Intuos2 12x18 " , 10 , 45720 , 31680 , 1023 , 15 , INTUOS , wacom_intuos_irq } ,
{ " Wacom Intuos3 4x5 " , 10 , 25400 , 20320 , 1023 , 15 , INTUOS3 , wacom_intuos_irq } ,
{ " Wacom Intuos3 6x8 " , 10 , 40640 , 30480 , 1023 , 15 , INTUOS3 , wacom_intuos_irq } ,
{ " Wacom Intuos3 9x12 " , 10 , 60960 , 45720 , 1023 , 15 , INTUOS3 , wacom_intuos_irq } ,
2005-11-17 20:46:51 +03:00
{ " Wacom Intuos3 6x11 " , 10 , 54204 , 31750 , 1023 , 15 , INTUOS3 , wacom_intuos_irq } ,
2005-06-06 11:25:50 +04:00
{ " Wacom Cintiq 21UX " , 10 , 87200 , 65600 , 1023 , 15 , CINTIQ , wacom_intuos_irq } ,
{ " Wacom Intuos2 6x8 " , 10 , 20320 , 16240 , 1023 , 15 , INTUOS , wacom_intuos_irq } ,
2005-05-29 11:29:01 +04:00
{ }
2005-04-17 02:20:36 +04:00
} ;
static struct usb_device_id wacom_ids [ ] = {
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x00 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x10 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x11 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x12 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x13 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x14 ) } ,
2005-11-17 20:46:51 +03:00
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x15 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x16 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x60 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x61 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x62 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x63 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x64 ) } ,
2005-04-17 02:20:36 +04:00
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x20 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x21 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x22 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x23 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x24 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x30 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x31 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x32 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x33 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x34 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x35 ) } ,
2005-11-17 20:46:51 +03:00
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x37 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x38 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x39 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0xC0 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x03 ) } ,
2005-04-17 02:20:36 +04:00
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x41 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x42 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x43 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x44 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x45 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0xB0 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0xB1 ) } ,
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0xB2 ) } ,
2005-11-17 20:46:51 +03:00
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0xB5 ) } ,
2005-06-06 11:25:50 +04:00
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x3F ) } ,
2005-04-17 02:20:36 +04:00
{ USB_DEVICE ( USB_VENDOR_ID_WACOM , 0x47 ) } ,
{ }
} ;
MODULE_DEVICE_TABLE ( usb , wacom_ids ) ;
static int wacom_open ( struct input_dev * dev )
{
struct wacom * wacom = dev - > private ;
wacom - > irq - > dev = wacom - > usbdev ;
2005-05-29 11:29:38 +04:00
if ( usb_submit_urb ( wacom - > irq , GFP_KERNEL ) )
2005-04-17 02:20:36 +04:00
return - EIO ;
return 0 ;
}
static void wacom_close ( struct input_dev * dev )
{
struct wacom * wacom = dev - > private ;
2005-05-29 11:29:38 +04:00
usb_kill_urb ( wacom - > irq ) ;
2005-04-17 02:20:36 +04:00
}
static int wacom_probe ( struct usb_interface * intf , const struct usb_device_id * id )
{
struct usb_device * dev = interface_to_usbdev ( intf ) ;
struct usb_endpoint_descriptor * endpoint ;
struct wacom * wacom ;
2005-09-15 11:01:47 +04:00
struct input_dev * input_dev ;
char rep_data [ 2 ] = { 0x02 , 0x02 } ;
2005-04-17 02:20:36 +04:00
2005-09-15 11:01:47 +04:00
wacom = kzalloc ( sizeof ( struct wacom ) , GFP_KERNEL ) ;
input_dev = input_allocate_device ( ) ;
if ( ! wacom | | ! input_dev )
goto fail1 ;
2005-04-17 02:20:36 +04:00
wacom - > data = usb_buffer_alloc ( dev , 10 , GFP_KERNEL , & wacom - > data_dma ) ;
2005-09-15 11:01:47 +04:00
if ( ! wacom - > data )
goto fail1 ;
2005-04-17 02:20:36 +04:00
wacom - > irq = usb_alloc_urb ( 0 , GFP_KERNEL ) ;
2005-09-15 11:01:47 +04:00
if ( ! wacom - > irq )
goto fail2 ;
wacom - > usbdev = dev ;
wacom - > dev = input_dev ;
usb_make_path ( dev , wacom - > phys , sizeof ( wacom - > phys ) ) ;
strlcat ( wacom - > phys , " /input0 " , sizeof ( wacom - > phys ) ) ;
2005-04-17 02:20:36 +04:00
wacom - > features = wacom_features + ( id - wacom_ids ) ;
2005-09-15 11:01:47 +04:00
if ( wacom - > features - > pktlen > 10 )
BUG ( ) ;
input_dev - > name = wacom - > features - > name ;
usb_to_input_id ( dev , & input_dev - > id ) ;
2005-04-17 02:20:36 +04:00
2005-09-15 11:01:47 +04:00
input_dev - > cdev . dev = & intf - > dev ;
input_dev - > private = wacom ;
input_dev - > open = wacom_open ;
input_dev - > close = wacom_close ;
input_dev - > evbit [ 0 ] | = BIT ( EV_KEY ) | BIT ( EV_ABS ) ;
input_dev - > keybit [ LONG ( BTN_DIGI ) ] | = BIT ( BTN_TOOL_PEN ) | BIT ( BTN_TOUCH ) | BIT ( BTN_STYLUS ) ;
2005-12-30 06:19:09 +03:00
input_set_abs_params ( input_dev , ABS_X , 0 , wacom - > features - > x_max , 4 , 0 ) ;
2005-09-15 11:01:47 +04:00
input_set_abs_params ( input_dev , ABS_Y , 0 , wacom - > features - > y_max , 4 , 0 ) ;
input_set_abs_params ( input_dev , ABS_PRESSURE , 0 , wacom - > features - > pressure_max , 0 , 0 ) ;
2005-04-17 02:20:36 +04:00
switch ( wacom - > features - > type ) {
2005-11-17 20:46:51 +03:00
case G4 :
input_dev - > evbit [ 0 ] | = BIT ( EV_MSC ) ;
input_dev - > mscbit [ 0 ] | = BIT ( MSC_SERIAL ) ;
input_dev - > keybit [ LONG ( BTN_DIGI ) ] | = BIT ( BTN_TOOL_FINGER ) ;
input_dev - > keybit [ LONG ( BTN_LEFT ) ] | = BIT ( BTN_0 ) | BIT ( BTN_1 ) | BIT ( BTN_2 ) | BIT ( BTN_3 ) | BIT ( BTN_4 ) | BIT ( BTN_5 ) | BIT ( BTN_6 ) | BIT ( BTN_7 ) ;
/* fall through */
2005-06-06 11:25:50 +04:00
case GRAPHIRE :
2005-09-15 11:01:47 +04:00
input_dev - > evbit [ 0 ] | = BIT ( EV_REL ) ;
input_dev - > relbit [ 0 ] | = BIT ( REL_WHEEL ) ;
input_dev - > keybit [ LONG ( BTN_LEFT ) ] | = BIT ( BTN_LEFT ) | BIT ( BTN_RIGHT ) | BIT ( BTN_MIDDLE ) ;
input_dev - > keybit [ LONG ( BTN_DIGI ) ] | = BIT ( BTN_TOOL_RUBBER ) | BIT ( BTN_TOOL_MOUSE ) | BIT ( BTN_STYLUS2 ) ;
input_set_abs_params ( input_dev , ABS_DISTANCE , 0 , wacom - > features - > distance_max , 0 , 0 ) ;
2005-04-17 02:20:36 +04:00
break ;
2005-06-06 11:25:50 +04:00
case INTUOS3 :
case CINTIQ :
2005-09-15 11:01:47 +04:00
input_dev - > keybit [ LONG ( BTN_DIGI ) ] | = BIT ( BTN_TOOL_FINGER ) ;
input_dev - > keybit [ LONG ( BTN_LEFT ) ] | = BIT ( BTN_0 ) | BIT ( BTN_1 ) | BIT ( BTN_2 ) | BIT ( BTN_3 ) | BIT ( BTN_4 ) | BIT ( BTN_5 ) | BIT ( BTN_6 ) | BIT ( BTN_7 ) ;
input_set_abs_params ( input_dev , ABS_RX , 0 , 4097 , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_RY , 0 , 4097 , 0 , 0 ) ;
2005-04-17 02:20:36 +04:00
/* fall through */
2005-06-06 11:25:50 +04:00
case INTUOS :
2005-09-15 11:01:47 +04:00
input_dev - > evbit [ 0 ] | = BIT ( EV_MSC ) | BIT ( EV_REL ) ;
input_dev - > mscbit [ 0 ] | = BIT ( MSC_SERIAL ) ;
input_dev - > relbit [ 0 ] | = BIT ( REL_WHEEL ) ;
input_dev - > keybit [ LONG ( BTN_LEFT ) ] | = BIT ( BTN_LEFT ) | BIT ( BTN_RIGHT ) | BIT ( BTN_MIDDLE ) | BIT ( BTN_SIDE ) | BIT ( BTN_EXTRA ) ;
input_dev - > keybit [ LONG ( BTN_DIGI ) ] | = BIT ( BTN_TOOL_RUBBER ) | BIT ( BTN_TOOL_MOUSE ) | BIT ( BTN_TOOL_BRUSH )
2005-04-17 02:20:36 +04:00
| BIT ( BTN_TOOL_PENCIL ) | BIT ( BTN_TOOL_AIRBRUSH ) | BIT ( BTN_TOOL_LENS ) | BIT ( BTN_STYLUS2 ) ;
2005-09-15 11:01:47 +04:00
input_set_abs_params ( input_dev , ABS_DISTANCE , 0 , wacom - > features - > distance_max , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_WHEEL , 0 , 1023 , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_TILT_X , 0 , 127 , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_TILT_Y , 0 , 127 , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_RZ , - 900 , 899 , 0 , 0 ) ;
input_set_abs_params ( input_dev , ABS_THROTTLE , - 1023 , 1023 , 0 , 0 ) ;
2005-04-17 02:20:36 +04:00
break ;
2005-06-06 11:25:50 +04:00
case PL :
2005-09-15 11:01:47 +04:00
input_dev - > keybit [ LONG ( BTN_DIGI ) ] | = BIT ( BTN_STYLUS2 ) | BIT ( BTN_TOOL_RUBBER ) ;
2005-04-17 02:20:36 +04:00
break ;
}
endpoint = & intf - > cur_altsetting - > endpoint [ 0 ] . desc ;
if ( wacom - > features - > pktlen > 10 )
BUG ( ) ;
usb_fill_int_urb ( wacom - > irq , dev ,
usb_rcvintpipe ( dev , endpoint - > bEndpointAddress ) ,
wacom - > data , wacom - > features - > pktlen ,
wacom - > features - > irq , wacom , endpoint - > bInterval ) ;
wacom - > irq - > transfer_dma = wacom - > data_dma ;
wacom - > irq - > transfer_flags | = URB_NO_TRANSFER_DMA_MAP ;
2005-09-15 11:01:47 +04:00
input_register_device ( wacom - > dev ) ;
2005-04-17 02:20:36 +04:00
/* ask the tablet to report tablet data */
usb_set_report ( intf , 3 , 2 , rep_data , 2 ) ;
/* repeat once (not sure why the first call often fails) */
usb_set_report ( intf , 3 , 2 , rep_data , 2 ) ;
usb_set_intfdata ( intf , wacom ) ;
return 0 ;
2005-09-15 11:01:47 +04:00
fail2 : usb_buffer_free ( dev , 10 , wacom - > data , wacom - > data_dma ) ;
fail1 : input_free_device ( input_dev ) ;
kfree ( wacom ) ;
return - ENOMEM ;
2005-04-17 02:20:36 +04:00
}
static void wacom_disconnect ( struct usb_interface * intf )
{
struct wacom * wacom = usb_get_intfdata ( intf ) ;
usb_set_intfdata ( intf , NULL ) ;
if ( wacom ) {
usb_kill_urb ( wacom - > irq ) ;
2005-09-15 11:01:47 +04:00
input_unregister_device ( wacom - > dev ) ;
2005-04-17 02:20:36 +04:00
usb_free_urb ( wacom - > irq ) ;
usb_buffer_free ( interface_to_usbdev ( intf ) , 10 , wacom - > data , wacom - > data_dma ) ;
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 )
{
int result = usb_register ( & wacom_driver ) ;
if ( result = = 0 )
info ( DRIVER_VERSION " : " DRIVER_DESC ) ;
return result ;
}
static void __exit wacom_exit ( void )
{
usb_deregister ( & wacom_driver ) ;
}
module_init ( wacom_init ) ;
module_exit ( wacom_exit ) ;