@ -42,7 +42,7 @@ MODULE_LICENSE(DRIVER_LICENSE);
# define HANWANG_TABLET_INT_SUB_CLASS 0x0001
# define HANWANG_TABLET_INT_PROTOCOL 0x0002
# define ART_MASTERIII _PKGLEN_MAX 10
# define ART_MASTER_PKGLEN_MAX 10
/* device IDs */
# define STYLUS_DEVICE_ID 0x02
@ -60,6 +60,11 @@ MODULE_LICENSE(DRIVER_LICENSE);
. bInterfaceSubClass = ( sc ) , \
. bInterfaceProtocol = ( pr )
enum hanwang_tablet_type {
HANWANG_ART_MASTER_III ,
HANWANG_ART_MASTER_HD ,
} ;
struct hanwang {
unsigned char * data ;
dma_addr_t data_dma ;
@ -76,6 +81,7 @@ struct hanwang {
struct hanwang_features {
unsigned short pid ;
char * name ;
enum hanwang_tablet_type type ;
int pkg_len ;
int max_x ;
int max_y ;
@ -85,12 +91,14 @@ struct hanwang_features {
} ;
static const struct hanwang_features features_array [ ] = {
{ 0x8528 , " Hanwang Art Master III 0906 " ,
ART_MASTERIII_PKGLEN_MAX , 0x5757 , 0x3692 , 0x3f , 0x7f , 2048 } ,
{ 0x8529 , " Hanwang Art Master III 0604 " ,
ART_MASTERIII_PKGLEN_MAX , 0x3d84 , 0x2672 , 0x3f , 0x7f , 2048 } ,
{ 0x852a , " Hanwang Art Master III 1308 " ,
ART_MASTERIII_PKGLEN_MAX , 0x7f00 , 0x4f60 , 0x3f , 0x7f , 2048 } ,
{ 0x8528 , " Hanwang Art Master III 0906 " , HANWANG_ART_MASTER_III ,
ART_MASTER_PKGLEN_MAX , 0x5757 , 0x3692 , 0x3f , 0x7f , 2048 } ,
{ 0x8529 , " Hanwang Art Master III 0604 " , HANWANG_ART_MASTER_III ,
ART_MASTER_PKGLEN_MAX , 0x3d84 , 0x2672 , 0x3f , 0x7f , 2048 } ,
{ 0x852a , " Hanwang Art Master III 1308 " , HANWANG_ART_MASTER_III ,
ART_MASTER_PKGLEN_MAX , 0x7f00 , 0x4f60 , 0x3f , 0x7f , 2048 } ,
{ 0x8401 , " Hanwang Art Master HD 5012 " , HANWANG_ART_MASTER_HD ,
ART_MASTER_PKGLEN_MAX , 0x678e , 0x4150 , 0x3f , 0x7f , 1024 } ,
} ;
static const int hw_eventtypes [ ] = {
@ -99,7 +107,7 @@ static const int hw_eventtypes[] = {
static const int hw_absevents [ ] = {
ABS_X , ABS_Y , ABS_TILT_X , ABS_TILT_Y , ABS_WHEEL ,
ABS_PRESSURE , ABS_MISC ,
ABS_RX , ABS_RY , ABS_ PRESSURE , ABS_MISC ,
} ;
static const int hw_btnevents [ ] = {
@ -117,7 +125,9 @@ static void hanwang_parse_packet(struct hanwang *hanwang)
unsigned char * data = hanwang - > data ;
struct input_dev * input_dev = hanwang - > dev ;
struct usb_device * dev = hanwang - > usbdev ;
enum hanwang_tablet_type type = hanwang - > features - > type ;
int i ;
u16 x , y , p ;
switch ( data [ 0 ] ) {
case 0x02 : /* data packet */
@ -129,12 +139,14 @@ static void hanwang_parse_packet(struct hanwang *hanwang)
case 0xc2 : /* first time tool prox in */
switch ( data [ 3 ] & 0xf0 ) {
case 0x20 :
case 0x20 : /* art_master III */
case 0x30 : /* art_master_HD */
hanwang - > current_id = STYLUS_DEVICE_ID ;
hanwang - > current_tool = BTN_TOOL_PEN ;
input_report_key ( input_dev , BTN_TOOL_PEN , 1 ) ;
break ;
case 0xa0 :
case 0xa0 : /* art_master III */
case 0xb0 : /* art_master_HD */
hanwang - > current_id = ERASER_DEVICE_ID ;
hanwang - > current_tool = BTN_TOOL_RUBBER ;
input_report_key ( input_dev , BTN_TOOL_RUBBER , 1 ) ;
@ -148,14 +160,31 @@ static void hanwang_parse_packet(struct hanwang *hanwang)
break ;
default : /* tool data packet */
x = ( data [ 2 ] < < 8 ) | data [ 3 ] ;
y = ( data [ 4 ] < < 8 ) | data [ 5 ] ;
switch ( type ) {
case HANWANG_ART_MASTER_III :
p = ( data [ 6 ] < < 3 ) |
( ( data [ 7 ] & 0xc0 ) > > 5 ) |
( data [ 1 ] & 0x01 ) ;
break ;
case HANWANG_ART_MASTER_HD :
p = ( data [ 7 ] > > 6 ) | ( data [ 6 ] < < 2 ) ;
break ;
default :
p = 0 ;
break ;
}
input_report_abs ( input_dev , ABS_X ,
( data [ 2 ] < < 8 ) | data [ 3 ] ) ;
le16_to_cpup ( ( __le16 * ) & x ) ) ;
input_report_abs ( input_dev , ABS_Y ,
( data [ 4 ] < < 8 ) | data [ 5 ] ) ;
le16_to_cpup ( ( __le16 * ) & y ) ) ;
input_report_abs ( input_dev , ABS_PRESSURE ,
( data [ 6 ] < < 3 ) |
( ( data [ 7 ] & 0xc0 ) > > 5 ) |
( data [ 1 ] & 0x01 ) ) ;
le16_to_cpup ( ( __le16 * ) & p ) ) ;
input_report_abs ( input_dev , ABS_TILT_X , data [ 7 ] & 0x3f ) ;
input_report_abs ( input_dev , ABS_TILT_Y , data [ 8 ] & 0x7f ) ;
input_report_key ( input_dev , BTN_STYLUS , data [ 1 ] & 0x02 ) ;
@ -170,13 +199,36 @@ static void hanwang_parse_packet(struct hanwang *hanwang)
case 0x0c :
/* roll wheel */
hanwang - > current_id = PAD_DEVICE_ID ;
input_report_key ( input_dev , BTN_TOOL_FINGER , data [ 1 ] | |
data [ 2 ] | | data [ 3 ] ) ;
input_report_abs ( input_dev , ABS_WHEEL , data [ 1 ] ) ;
input_report_key ( input_dev , BTN_0 , data [ 2 ] ) ;
for ( i = 0 ; i < 8 ; i + + )
input_report_key ( input_dev ,
switch ( type ) {
case HANWANG_ART_MASTER_III :
input_report_key ( input_dev , BTN_TOOL_FINGER , data [ 1 ] | |
data [ 2 ] | | data [ 3 ] ) ;
input_report_abs ( input_dev , ABS_WHEEL , data [ 1 ] ) ;
input_report_key ( input_dev , BTN_0 , data [ 2 ] ) ;
for ( i = 0 ; i < 8 ; i + + )
input_report_key ( input_dev ,
BTN_1 + i , data [ 3 ] & ( 1 < < i ) ) ;
break ;
case HANWANG_ART_MASTER_HD :
input_report_key ( input_dev , BTN_TOOL_FINGER , data [ 1 ] | |
data [ 2 ] | | data [ 3 ] | | data [ 4 ] | |
data [ 5 ] | | data [ 6 ] ) ;
input_report_abs ( input_dev , ABS_RX ,
( ( data [ 1 ] & 0x1f ) < < 8 ) | data [ 2 ] ) ;
input_report_abs ( input_dev , ABS_RY ,
( ( data [ 3 ] & 0x1f ) < < 8 ) | data [ 4 ] ) ;
input_report_key ( input_dev , BTN_0 , data [ 5 ] & 0x01 ) ;
for ( i = 0 ; i < 4 ; i + + ) {
input_report_key ( input_dev ,
BTN_1 + i , data [ 5 ] & ( 1 < < i ) ) ;
input_report_key ( input_dev ,
BTN_5 + i , data [ 6 ] & ( 1 < < i ) ) ;
}
break ;
}
input_report_abs ( input_dev , ABS_MISC , hanwang - > current_id ) ;
input_event ( input_dev , EV_MSC , MSC_SERIAL , 0xffffffff ) ;
break ;