Commit 2a3e480d authored by Dmitry Torokhov's avatar Dmitry Torokhov

Input: appletouch - idle reset logic broke older Fountains

Fountains do not support change mode request and therefore
should be excluded from idle reset attempts.

Also:
 - do not re-submit URB when we decide that touchpad needs to be
   reinicialized
 - do not repeat size detection when reinitializing the touchpad
 - Add missing KERN_* prefixes to messages
Signed-off-by: default avatarDmitry Torokhov <dtor@mail.ru>
Acked-by: default avatarJohannes Berg <johannes@sipsolutions.net>
parent 167ebf76
...@@ -129,12 +129,12 @@ MODULE_DEVICE_TABLE (usb, atp_table); ...@@ -129,12 +129,12 @@ MODULE_DEVICE_TABLE (usb, atp_table);
*/ */
#define ATP_THRESHOLD 5 #define ATP_THRESHOLD 5
/* MacBook Pro (Geyser 3 & 4) initialization constants */ /* Geyser initialization constants */
#define ATP_GEYSER3_MODE_READ_REQUEST_ID 1 #define ATP_GEYSER_MODE_READ_REQUEST_ID 1
#define ATP_GEYSER3_MODE_WRITE_REQUEST_ID 9 #define ATP_GEYSER_MODE_WRITE_REQUEST_ID 9
#define ATP_GEYSER3_MODE_REQUEST_VALUE 0x300 #define ATP_GEYSER_MODE_REQUEST_VALUE 0x300
#define ATP_GEYSER3_MODE_REQUEST_INDEX 0 #define ATP_GEYSER_MODE_REQUEST_INDEX 0
#define ATP_GEYSER3_MODE_VENDOR_VALUE 0x04 #define ATP_GEYSER_MODE_VENDOR_VALUE 0x04
/* Structure to hold all of our device specific stuff */ /* Structure to hold all of our device specific stuff */
struct atp { struct atp {
...@@ -142,9 +142,11 @@ struct atp { ...@@ -142,9 +142,11 @@ struct atp {
struct usb_device * udev; /* usb device */ struct usb_device * udev; /* usb device */
struct urb * urb; /* usb request block */ struct urb * urb; /* usb request block */
signed char * data; /* transferred data */ signed char * data; /* transferred data */
int open; /* non-zero if opened */ struct input_dev * input; /* input dev */
struct input_dev *input; /* input dev */ unsigned char open; /* non-zero if opened */
int valid; /* are the sensors valid ? */ unsigned char valid; /* are the sensors valid ? */
unsigned char size_detect_done;
unsigned char overflowwarn; /* overflow warning printed? */
int x_old; /* last reported x/y, */ int x_old; /* last reported x/y, */
int y_old; /* used for smoothing */ int y_old; /* used for smoothing */
/* current value of the sensors */ /* current value of the sensors */
...@@ -153,7 +155,6 @@ struct atp { ...@@ -153,7 +155,6 @@ struct atp {
signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; signed char xy_old[ATP_XSENSORS + ATP_YSENSORS];
/* accumulated sensors */ /* accumulated sensors */
int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; int xy_acc[ATP_XSENSORS + ATP_YSENSORS];
int overflowwarn; /* overflow warning printed? */
int datalen; /* size of an USB urb transfer */ int datalen; /* size of an USB urb transfer */
int idlecount; /* number of empty packets */ int idlecount; /* number of empty packets */
struct work_struct work; struct work_struct work;
...@@ -170,7 +171,7 @@ struct atp { ...@@ -170,7 +171,7 @@ struct atp {
#define dprintk(format, a...) \ #define dprintk(format, a...) \
do { \ do { \
if (debug) printk(format, ##a); \ if (debug) printk(KERN_DEBUG format, ##a); \
} while (0) } while (0)
MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann"); MODULE_AUTHOR("Johannes Berg, Stelian Pop, Frank Arnold, Michael Hanselmann");
...@@ -188,6 +189,15 @@ static int debug = 1; ...@@ -188,6 +189,15 @@ static int debug = 1;
module_param(debug, int, 0644); module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Activate debugging output"); MODULE_PARM_DESC(debug, "Activate debugging output");
static inline int atp_is_fountain(struct atp *dev)
{
u16 productId = le16_to_cpu(dev->udev->descriptor.idProduct);
return productId == FOUNTAIN_ANSI_PRODUCT_ID ||
productId == FOUNTAIN_ISO_PRODUCT_ID ||
productId == FOUNTAIN_TP_ONLY_PRODUCT_ID;
}
/* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */ /* Checks if the device a Geyser 2 (ANSI, ISO, JIS) */
static inline int atp_is_geyser_2(struct atp *dev) static inline int atp_is_geyser_2(struct atp *dev)
{ {
...@@ -211,52 +221,63 @@ static inline int atp_is_geyser_3(struct atp *dev) ...@@ -211,52 +221,63 @@ static inline int atp_is_geyser_3(struct atp *dev)
} }
/* /*
* By default Geyser 3 device sends standard USB HID mouse * By default newer Geyser devices send standard USB HID mouse
* packets (Report ID 2). This code changes device mode, so it * packets (Report ID 2). This code changes device mode, so it
* sends raw sensor reports (Report ID 5). * sends raw sensor reports (Report ID 5).
*/ */
static int atp_geyser3_init(struct usb_device *udev) static int atp_geyser_init(struct usb_device *udev)
{ {
char data[8]; char data[8];
int size; int size;
size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
ATP_GEYSER3_MODE_READ_REQUEST_ID, ATP_GEYSER_MODE_READ_REQUEST_ID,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
ATP_GEYSER3_MODE_REQUEST_VALUE, ATP_GEYSER_MODE_REQUEST_VALUE,
ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
if (size != 8) { if (size != 8) {
err("Could not do mode read request from device" err("Could not do mode read request from device"
" (Geyser 3 mode)"); " (Geyser Raw mode)");
return -EIO; return -EIO;
} }
/* Apply the mode switch */ /* Apply the mode switch */
data[0] = ATP_GEYSER3_MODE_VENDOR_VALUE; data[0] = ATP_GEYSER_MODE_VENDOR_VALUE;
size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), size = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
ATP_GEYSER3_MODE_WRITE_REQUEST_ID, ATP_GEYSER_MODE_WRITE_REQUEST_ID,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
ATP_GEYSER3_MODE_REQUEST_VALUE, ATP_GEYSER_MODE_REQUEST_VALUE,
ATP_GEYSER3_MODE_REQUEST_INDEX, &data, 8, 5000); ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
if (size != 8) { if (size != 8) {
err("Could not do mode write request to device" err("Could not do mode write request to device"
" (Geyser 3 mode)"); " (Geyser Raw mode)");
return -EIO; return -EIO;
} }
return 0; return 0;
} }
/* Reinitialise the device if it's a geyser 3 */ /*
* Reinitialise the device. This usually stops stream of empty packets
* coming from it.
*/
static void atp_reinit(struct work_struct *work) static void atp_reinit(struct work_struct *work)
{ {
struct atp *dev = container_of(work, struct atp, work); struct atp *dev = container_of(work, struct atp, work);
struct usb_device *udev = dev->udev; struct usb_device *udev = dev->udev;
int retval;
dev->idlecount = 0; dev->idlecount = 0;
atp_geyser3_init(udev);
atp_geyser_init(udev);
retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
if (retval) {
err("%s - usb_submit_urb failed with result %d",
__FUNCTION__, retval);
}
} }
static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact, static int atp_calculate_abs(int *xy_sensors, int nb_sensors, int fact,
...@@ -337,7 +358,7 @@ static void atp_complete(struct urb* urb) ...@@ -337,7 +358,7 @@ static void atp_complete(struct urb* urb)
break; break;
case -EOVERFLOW: case -EOVERFLOW:
if(!dev->overflowwarn) { if(!dev->overflowwarn) {
printk("appletouch: OVERFLOW with data " printk(KERN_WARNING "appletouch: OVERFLOW with data "
"length %d, actual length is %d\n", "length %d, actual length is %d\n",
dev->datalen, dev->urb->actual_length); dev->datalen, dev->urb->actual_length);
dev->overflowwarn = 1; dev->overflowwarn = 1;
...@@ -426,15 +447,17 @@ static void atp_complete(struct urb* urb) ...@@ -426,15 +447,17 @@ static void atp_complete(struct urb* urb)
dev->x_old = dev->y_old = -1; dev->x_old = dev->y_old = -1;
memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old)); memcpy(dev->xy_old, dev->xy_cur, sizeof(dev->xy_old));
if (atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */ if (dev->size_detect_done ||
atp_is_geyser_3(dev)) /* No 17" Macbooks (yet) */
goto exit; goto exit;
/* 17" Powerbooks have extra X sensors */ /* 17" Powerbooks have extra X sensors */
for (i = (atp_is_geyser_2(dev)?15:16); i < ATP_XSENSORS; i++) { for (i = (atp_is_geyser_2(dev) ? 15 : 16); i < ATP_XSENSORS; i++) {
if (!dev->xy_cur[i]) continue; if (!dev->xy_cur[i])
continue;
printk("appletouch: 17\" model detected.\n"); printk(KERN_INFO "appletouch: 17\" model detected.\n");
if(atp_is_geyser_2(dev)) if (atp_is_geyser_2(dev))
input_set_abs_params(dev->input, ABS_X, 0, input_set_abs_params(dev->input, ABS_X, 0,
(20 - 1) * (20 - 1) *
ATP_XFACT - 1, ATP_XFACT - 1,
...@@ -444,10 +467,10 @@ static void atp_complete(struct urb* urb) ...@@ -444,10 +467,10 @@ static void atp_complete(struct urb* urb)
(ATP_XSENSORS - 1) * (ATP_XSENSORS - 1) *
ATP_XFACT - 1, ATP_XFACT - 1,
ATP_FUZZ, 0); ATP_FUZZ, 0);
break; break;
} }
dev->size_detect_done = 1;
goto exit; goto exit;
} }
...@@ -479,7 +502,7 @@ static void atp_complete(struct urb* urb) ...@@ -479,7 +502,7 @@ static void atp_complete(struct urb* urb)
dev->y_old = y; dev->y_old = y;
if (debug > 1) if (debug > 1)
printk("appletouch: X: %3d Y: %3d " printk(KERN_DEBUG "appletouch: X: %3d Y: %3d "
"Xz: %3d Yz: %3d\n", "Xz: %3d Yz: %3d\n",
x, y, x_z, y_z); x, y, x_z, y_z);
...@@ -507,19 +530,25 @@ static void atp_complete(struct urb* urb) ...@@ -507,19 +530,25 @@ static void atp_complete(struct urb* urb)
input_report_key(dev->input, BTN_LEFT, key); input_report_key(dev->input, BTN_LEFT, key);
input_sync(dev->input); input_sync(dev->input);
/* Many Geysers will continue to send packets continually after /*
the first touch unless reinitialised. Do so if it's been * Many Geysers will continue to send packets continually after
idle for a while in order to avoid waking the kernel up * the first touch unless reinitialised. Do so if it's been
several hundred times a second */ * idle for a while in order to avoid waking the kernel up
* several hundred times a second. Re-initialization does not
if (!x && !y && !key) { * work on Fountain touchpads.
dev->idlecount++; */
if (dev->idlecount == 10) { if (!atp_is_fountain(dev)) {
dev->valid = 0; if (!x && !y && !key) {
schedule_work(&dev->work); dev->idlecount++;
} if (dev->idlecount == 10) {
} else dev->valid = 0;
dev->idlecount = 0; schedule_work(&dev->work);
/* Don't resubmit urb here, wait for reinit */
return;
}
} else
dev->idlecount = 0;
}
exit: exit:
retval = usb_submit_urb(dev->urb, GFP_ATOMIC); retval = usb_submit_urb(dev->urb, GFP_ATOMIC);
...@@ -593,12 +622,12 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id ...@@ -593,12 +622,12 @@ static int atp_probe(struct usb_interface *iface, const struct usb_device_id *id
else else
dev->datalen = 81; dev->datalen = 81;
if (atp_is_geyser_3(dev)) { if (!atp_is_fountain(dev)) {
/* switch to raw sensor mode */ /* switch to raw sensor mode */
if (atp_geyser3_init(udev)) if (atp_geyser_init(udev))
goto err_free_devs; goto err_free_devs;
printk("appletouch Geyser 3 inited.\n"); printk(KERN_INFO "appletouch: Geyser mode initialized.\n");
} }
dev->urb = usb_alloc_urb(0, GFP_KERNEL); dev->urb = usb_alloc_urb(0, GFP_KERNEL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment