From e33da8a5486aaadf5161118869e6cfb3d119beea Mon Sep 17 00:00:00 2001 From: Jason Childs Date: Wed, 17 Feb 2010 22:38:31 -0800 Subject: [PATCH] Input: wacom - use per-device instance of wacom_features Since we mangle data in wacom_features when dealing with certain devices let's use a private (per-device) instance of wacom_features in wacom_wac. This way same product ID can support more than one type of device, such as pen and touch, and not interfere with each other. Signed-off-by: Jason Childs Signed-off-by: Ping Cheng Signed-off-by: Dmitry Torokhov --- drivers/input/tablet/wacom_sys.c | 58 ++++++++++++++++++++++------------- drivers/input/tablet/wacom_wac.c | 66 ++++++++++++++++++++++------------------ drivers/input/tablet/wacom_wac.h | 10 +++--- 3 files changed, 78 insertions(+), 56 deletions(-) diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index be4b76f..f22b88d 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -211,7 +211,8 @@ void input_dev_g(struct input_dev *input_dev, struct wacom_wac *wacom_wac) input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_RUBBER) | BIT_MASK(BTN_TOOL_PEN) | BIT_MASK(BTN_STYLUS) | BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_STYLUS2); - input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); + input_set_abs_params(input_dev, ABS_DISTANCE, + 0, wacom_wac->features.distance_max, 0, 0); } void input_dev_i3s(struct input_dev *input_dev, struct wacom_wac *wacom_wac) @@ -261,7 +262,8 @@ void input_dev_i(struct input_dev *input_dev, struct wacom_wac *wacom_wac) BIT_MASK(BTN_TOOL_MOUSE) | BIT_MASK(BTN_TOOL_BRUSH) | BIT_MASK(BTN_TOOL_PENCIL) | BIT_MASK(BTN_TOOL_AIRBRUSH) | BIT_MASK(BTN_TOOL_LENS) | BIT_MASK(BTN_STYLUS2); - input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features->distance_max, 0, 0); + input_set_abs_params(input_dev, ABS_DISTANCE, + 0, wacom_wac->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); @@ -282,17 +284,19 @@ void input_dev_pt(struct input_dev *input_dev, struct wacom_wac *wacom_wac) void input_dev_tpc(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - if (wacom_wac->features->device_type == BTN_TOOL_DOUBLETAP || - wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) { - input_set_abs_params(input_dev, ABS_RX, 0, wacom_wac->features->x_phy, 0, 0); - input_set_abs_params(input_dev, ABS_RY, 0, wacom_wac->features->y_phy, 0, 0); - input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_DOUBLETAP); + struct wacom_features *features = &wacom_wac->features; + + if (features->device_type == BTN_TOOL_DOUBLETAP || + features->device_type == BTN_TOOL_TRIPLETAP) { + input_set_abs_params(input_dev, ABS_RX, 0, features->x_phy, 0, 0); + input_set_abs_params(input_dev, ABS_RY, 0, features->y_phy, 0, 0); + __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); } } void input_dev_tpc2fg(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - if (wacom_wac->features->device_type == BTN_TOOL_TRIPLETAP) { + if (wacom_wac->features.device_type == BTN_TOOL_TRIPLETAP) { input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOOL_TRIPLETAP); input_dev->evbit[0] |= BIT_MASK(EV_MSC); input_dev->mscbit[0] |= BIT_MASK(MSC_SERIAL); @@ -530,26 +534,40 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i struct usb_endpoint_descriptor *endpoint; struct wacom *wacom; struct wacom_wac *wacom_wac; - struct wacom_features *features = (void *)id->driver_info; + struct wacom_features *features; struct input_dev *input_dev; - int error = -ENOMEM; + int error; - if (!features) + if (!id->driver_info) return -EINVAL; wacom = kzalloc(sizeof(struct wacom), GFP_KERNEL); wacom_wac = kzalloc(sizeof(struct wacom_wac), GFP_KERNEL); input_dev = input_allocate_device(); - if (!wacom || !input_dev || !wacom_wac) + if (!wacom || !input_dev || !wacom_wac) { + error = -ENOMEM; + goto fail1; + } + + wacom_wac->features = *((struct wacom_features *)id->driver_info); + features = &wacom_wac->features; + if (features->pktlen > WACOM_PKGLEN_MAX) { + error = -EINVAL; goto fail1; + } - wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, GFP_KERNEL, &wacom->data_dma); - if (!wacom_wac->data) + wacom_wac->data = usb_buffer_alloc(dev, WACOM_PKGLEN_MAX, + GFP_KERNEL, &wacom->data_dma); + if (!wacom_wac->data) { + error = -ENOMEM; goto fail1; + } wacom->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!wacom->irq) + if (!wacom->irq) { + error = -ENOMEM; goto fail2; + } wacom->usbdev = dev; wacom->dev = input_dev; @@ -558,11 +576,6 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i usb_make_path(dev, wacom->phys, sizeof(wacom->phys)); strlcat(wacom->phys, "/input0", sizeof(wacom->phys)); - wacom_wac->features = features; - BUG_ON(features->pktlen > WACOM_PKGLEN_MAX); - - input_dev->name = wacom_wac->features->name; - wacom->wacom_wac = wacom_wac; usb_to_input_id(dev, &input_dev->id); input_dev->dev.parent = &intf->dev; @@ -579,6 +592,9 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i if (error) goto fail2; + input_dev->name = features->name; + wacom->wacom_wac = wacom_wac; + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); input_dev->keybit[BIT_WORD(BTN_DIGI)] |= BIT_MASK(BTN_TOUCH); @@ -643,7 +659,7 @@ static int wacom_suspend(struct usb_interface *intf, pm_message_t message) static int wacom_resume(struct usb_interface *intf) { struct wacom *wacom = usb_get_intfdata(intf); - struct wacom_features *features = wacom->wacom_wac->features; + struct wacom_features *features = &wacom->wacom_wac->features; int rv; mutex_lock(&wacom->lock); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 56aaf01..e4a1a7d 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -55,6 +55,7 @@ static int wacom_penpartner_irq(struct wacom_wac *wacom, void *wcombo) static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; int prox, pressure; @@ -68,9 +69,9 @@ static int wacom_pl_irq(struct wacom_wac *wacom, void *wcombo) if (prox) { wacom->id[0] = ERASER_DEVICE_ID; pressure = (signed char)((data[7] << 1) | ((data[4] >> 2) & 1)); - if (wacom->features->pressure_max > 255) + if (features->pressure_max > 255) pressure = (pressure << 1) | ((data[4] >> 6) & 1); - pressure += (wacom->features->pressure_max + 1) / 2; + pressure += (features->pressure_max + 1) / 2; /* * if going from out of proximity into proximity select between the eraser @@ -152,6 +153,7 @@ static int wacom_ptu_irq(struct wacom_wac *wacom, void *wcombo) static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; int x, y, rw; static int penData = 0; @@ -179,8 +181,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) case 2: /* Mouse with wheel */ wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); - if (wacom->features->type == WACOM_G4 || - wacom->features->type == WACOM_MO) { + if (features->type == WACOM_G4 || features->type == WACOM_MO) { rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); wacom_report_rel(wcombo, REL_WHEEL, -rw); } else @@ -192,8 +193,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom->id[0] = CURSOR_DEVICE_ID; wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); - if (wacom->features->type == WACOM_G4 || - wacom->features->type == WACOM_MO) + if (features->type == WACOM_G4 || features->type == WACOM_MO) wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); else wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); @@ -230,7 +230,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) } /* send pad data */ - switch (wacom->features->type) { + switch (features->type) { case WACOM_G4: if (data[7] & 0xf8) { if (penData) { @@ -300,11 +300,12 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; int idx = 0; /* tool number */ - if (wacom->features->type == INTUOS) + if (features->type == INTUOS) idx = data[1] & 0x01; /* Enter report */ @@ -402,7 +403,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_STYLUS2, 0); wacom_report_key(wcombo, BTN_TOUCH, 0); wacom_report_abs(wcombo, ABS_WHEEL, 0); - if (wacom->features->type >= INTUOS3S) + if (features->type >= INTUOS3S) wacom_report_abs(wcombo, ABS_Z, 0); } wacom_report_key(wcombo, wacom->tool[idx], 0); @@ -416,13 +417,14 @@ static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; unsigned int t; /* general pen packet */ if ((data[1] & 0xb8) == 0xa0) { t = (data[6] << 2) | ((data[7] >> 6) & 3); - if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) + if (features->type >= INTUOS4S && features->type <= INTUOS4L) t = (t << 1) | (data[1] & 1); wacom_report_abs(wcombo, ABS_PRESSURE, t); wacom_report_abs(wcombo, ABS_TILT_X, @@ -446,6 +448,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom, void *wcombo) static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; unsigned int t; int idx = 0, result; @@ -457,7 +460,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) } /* tool number */ - if (wacom->features->type == INTUOS) + if (features->type == INTUOS) idx = data[1] & 0x01; /* pad packets. Works as a second tool and is always in prox */ @@ -466,7 +469,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) if (wacom->tool[1] != BTN_TOOL_FINGER) wacom->tool[1] = BTN_TOOL_FINGER; - if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) { + if (features->type >= INTUOS4S && features->type <= INTUOS4L) { wacom_report_key(wcombo, BTN_0, (data[2] & 0x01)); wacom_report_key(wcombo, BTN_1, (data[3] & 0x01)); wacom_report_key(wcombo, BTN_2, (data[3] & 0x02)); @@ -480,7 +483,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) /* Out of proximity, clear wheel value. */ wacom_report_abs(wcombo, ABS_WHEEL, 0); } - if (wacom->features->type != INTUOS4S) { + if (features->type != INTUOS4S) { wacom_report_key(wcombo, BTN_7, (data[3] & 0x40)); wacom_report_key(wcombo, BTN_8, (data[3] & 0x80)); } @@ -528,18 +531,20 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) return 0; /* Only large Intuos support Lense Cursor */ - if ((wacom->tool[idx] == BTN_TOOL_LENS) - && ((wacom->features->type == INTUOS3) - || (wacom->features->type == INTUOS3S) - || (wacom->features->type == INTUOS4) - || (wacom->features->type == INTUOS4S))) + if (wacom->tool[idx] == BTN_TOOL_LENS && + (features->type == INTUOS3 || + features->type == INTUOS3S || + features->type == INTUOS4 || + features->type == INTUOS4S)) { + return 0; + } /* Cintiq doesn't send data when RDY bit isn't set */ - if ((wacom->features->type == CINTIQ) && !(data[1] & 0x40)) + if (features->type == CINTIQ && !(data[1] & 0x40)) return 0; - if (wacom->features->type >= INTUOS3S) { + if (features->type >= INTUOS3S) { wacom_report_abs(wcombo, ABS_X, (data[2] << 9) | (data[3] << 1) | ((data[9] >> 1) & 1)); wacom_report_abs(wcombo, ABS_Y, (data[4] << 9) | (data[5] << 1) | (data[9] & 1)); wacom_report_abs(wcombo, ABS_DISTANCE, ((data[9] >> 2) & 0x3f)); @@ -557,7 +562,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) if (data[1] & 0x02) { /* Rotation packet */ - if (wacom->features->type >= INTUOS3S) { + if (features->type >= INTUOS3S) { /* I3 marker pen rotation */ t = (data[6] << 3) | ((data[7] >> 5) & 7); t = (data[7] & 0x20) ? ((t > 900) ? ((t-1) / 2 - 1350) : @@ -570,7 +575,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) ((t - 1) / 2) : -t / 2); } - } else if (!(data[1] & 0x10) && wacom->features->type < INTUOS3S) { + } else if (!(data[1] & 0x10) && features->type < INTUOS3S) { /* 4D mouse packet */ wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); wacom_report_key(wcombo, BTN_MIDDLE, data[8] & 0x02); @@ -583,7 +588,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) } else if (wacom->tool[idx] == BTN_TOOL_MOUSE) { /* I4 mouse */ - if (wacom->features->type >= INTUOS4S && wacom->features->type <= INTUOS4L) { + if (features->type >= INTUOS4S && features->type <= INTUOS4L) { wacom_report_key(wcombo, BTN_LEFT, data[6] & 0x01); wacom_report_key(wcombo, BTN_MIDDLE, data[6] & 0x02); wacom_report_key(wcombo, BTN_RIGHT, data[6] & 0x04); @@ -604,13 +609,13 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) - ((data[8] & 0x02) >> 1)); /* I3 2D mouse side buttons */ - if (wacom->features->type >= INTUOS3S && wacom->features->type <= INTUOS3L) { + if (features->type >= INTUOS3S && features->type <= INTUOS3L) { wacom_report_key(wcombo, BTN_SIDE, data[8] & 0x40); wacom_report_key(wcombo, BTN_EXTRA, data[8] & 0x20); } } - } else if ((wacom->features->type < INTUOS3S || wacom->features->type == INTUOS3L || - wacom->features->type == INTUOS4L) && + } else if ((features->type < INTUOS3S || features->type == INTUOS3L || + features->type == INTUOS4L) && wacom->tool[idx] == BTN_TOOL_LENS) { /* Lens cursor packets */ wacom_report_key(wcombo, BTN_LEFT, data[8] & 0x01); @@ -718,6 +723,7 @@ static void wacom_tpc_touch_in(struct wacom_wac *wacom, void *wcombo) static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) { + struct wacom_features *features = &wacom->features; char *data = wacom->data; int prox = 0, pressure, idx = -1; static int stylusInProx, touchInProx = 1, touchOut; @@ -791,7 +797,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); pressure = ((data[7] & 0x01) << 8) | data[6]; if (pressure < 0) - pressure = wacom->features->pressure_max + pressure + 1; + pressure = features->pressure_max + pressure + 1; wacom_report_abs(wcombo, ABS_PRESSURE, pressure); wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); } else { @@ -815,7 +821,7 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) { - switch (wacom_wac->features->type) { + switch (wacom_wac->features.type) { case PENPARTNER: return wacom_penpartner_irq(wacom_wac, wcombo); @@ -853,7 +859,7 @@ int wacom_wac_irq(struct wacom_wac *wacom_wac, void *wcombo) void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { - switch (wacom_wac->features->type) { + switch (wacom_wac->features.type) { case WACOM_MO: input_dev_mo(input_dev, wacom_wac); case WACOM_G4: @@ -888,7 +894,7 @@ void wacom_init_input_dev(struct input_dev *input_dev, struct wacom_wac *wacom_w /* fall through */ case TABLETPC: input_dev_tpc(input_dev, wacom_wac); - if (wacom_wac->features->device_type != BTN_TOOL_PEN) + if (wacom_wac->features.device_type != BTN_TOOL_PEN) break; /* no need to process stylus stuff */ /* fall through */ diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index ee01e19..3f4b89d 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -15,11 +15,11 @@ /* packet length for individual models */ #define WACOM_PKGLEN_PENPRTN 7 #define WACOM_PKGLEN_GRAPHIRE 8 -#define WACOM_PKGLEN_BBFUN 9 -#define WACOM_PKGLEN_INTUOS 10 +#define WACOM_PKGLEN_BBFUN 9 +#define WACOM_PKGLEN_INTUOS 10 #define WACOM_PKGLEN_PENABLED 8 #define WACOM_PKGLEN_TPC1FG 5 -#define WACOM_PKGLEN_TPC2FG 14 +#define WACOM_PKGLEN_TPC2FG 14 /* device IDs */ #define STYLUS_DEVICE_ID 0x02 @@ -58,7 +58,7 @@ enum { }; struct wacom_features { - char *name; + const char *name; int pktlen; int x_max; int y_max; @@ -77,7 +77,7 @@ struct wacom_wac { int tool[2]; int id[2]; __u32 serial[2]; - struct wacom_features *features; + struct wacom_features features; }; #endif -- 2.7.4