Lines Matching +full:trackpad +full:- +full:3 +full:x
1 // SPDX-License-Identifier: GPL-2.0-or-later
9 * Scott Shawcroft as part of the touchd user-space driver project:
13 * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
16 * Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
18 * Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
170 u8 rel_x; /* relative x coordinate */
174 /* trackpad header types */
176 TYPE1, /* plain trackpad */
177 TYPE2, /* button integrated in trackpad */
182 /* trackpad finger data offsets, le16-aligned */
188 /* trackpad button data offsets */
197 /* trackpad finger data block size */
219 /* trackpad finger structure, le16-aligned */
222 __le16 abs_x; /* absolute x coodinate */
224 __le16 rel_x; /* relative x coodinate */
236 /* trackpad finger data size, empirically at least ten fingers */
240 /* device-specific parameters */
242 int snratio; /* signal-to-noise ratio */
247 /* device-specific configuration */
253 int tp_ep; /* the endpoint of the trackpad interface */
254 enum tp_type tp_type; /* type of trackpad interface */
256 int tp_datalen; /* data length of the trackpad interface */
268 struct bcm5974_param x; /* horizontal limits */ member
284 struct urb *tp_urb; /* trackpad usb request block */
285 u8 *tp_data; /* trackpad transferred data */
291 /* trackpad finger block data, le16-aligned */
294 const struct bcm5974_config *c = &dev->cfg; in get_tp_finger()
295 u8 *f_base = dev->tp_data + c->tp_header + c->tp_delta; in get_tp_finger()
297 return (const struct tp_finger *)(f_base + i * c->tp_fsize); in get_tp_finger()
310 #define SN_PRESSURE 45 /* pressure signal-to-noise ratio */
311 #define SN_WIDTH 25 /* width signal-to-noise ratio */
312 #define SN_COORD 250 /* coordinate signal-to-noise ratio */
313 #define SN_ORIENT 10 /* orientation signal-to-noise ratio */
326 { SN_COORD, -4824, 5342 },
327 { SN_COORD, -172, 5820 },
328 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
339 { SN_COORD, -4824, 4824 },
340 { SN_COORD, -172, 4290 },
341 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
352 { SN_COORD, -4460, 5166 },
353 { SN_COORD, -75, 6700 },
354 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
365 { SN_COORD, -4620, 5140 },
366 { SN_COORD, -150, 6600 },
367 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
378 { SN_COORD, -4616, 5112 },
379 { SN_COORD, -142, 5234 },
380 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
391 { SN_COORD, -4415, 5050 },
392 { SN_COORD, -55, 6680 },
393 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
404 { SN_COORD, -4620, 5140 },
405 { SN_COORD, -150, 6600 },
406 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
417 { SN_COORD, -4750, 5280 },
418 { SN_COORD, -150, 6730 },
419 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
430 { SN_COORD, -4620, 5140 },
431 { SN_COORD, -150, 6600 },
432 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
443 { SN_COORD, -4750, 5280 },
444 { SN_COORD, -150, 6730 },
445 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
456 { SN_COORD, -4750, 5280 },
457 { SN_COORD, -150, 6730 },
458 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
469 { SN_COORD, -4620, 5140 },
470 { SN_COORD, -150, 6600 },
471 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
482 { SN_COORD, -4828, 5345 },
483 { SN_COORD, -203, 6803 },
484 { SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }
489 /* return the device-specific configuration by device */
492 u16 id = le16_to_cpu(udev->descriptor.idProduct); in bcm5974_get_config()
495 for (cfg = bcm5974_config_table; cfg->ansi; ++cfg) in bcm5974_get_config()
496 if (cfg->ansi == id || cfg->iso == id || cfg->jis == id) in bcm5974_get_config()
502 /* convert 16-bit little endian to signed integer */
503 static inline int raw2int(__le16 x) in raw2int() argument
505 return (signed short)le16_to_cpu(x); in raw2int()
511 int fuzz = p->snratio ? (p->max - p->min) / p->snratio : 0; in set_abs()
512 input_set_abs_params(input, code, p->min, p->max, fuzz, 0); in set_abs()
519 __set_bit(EV_ABS, input_dev->evbit); in setup_events_to_report()
526 set_abs(input_dev, ABS_MT_TOUCH_MAJOR, &cfg->w); in setup_events_to_report()
527 set_abs(input_dev, ABS_MT_TOUCH_MINOR, &cfg->w); in setup_events_to_report()
529 set_abs(input_dev, ABS_MT_WIDTH_MAJOR, &cfg->w); in setup_events_to_report()
530 set_abs(input_dev, ABS_MT_WIDTH_MINOR, &cfg->w); in setup_events_to_report()
532 set_abs(input_dev, ABS_MT_ORIENTATION, &cfg->o); in setup_events_to_report()
534 set_abs(input_dev, ABS_MT_POSITION_X, &cfg->x); in setup_events_to_report()
535 set_abs(input_dev, ABS_MT_POSITION_Y, &cfg->y); in setup_events_to_report()
537 __set_bit(EV_KEY, input_dev->evbit); in setup_events_to_report()
538 __set_bit(BTN_LEFT, input_dev->keybit); in setup_events_to_report()
540 if (cfg->caps & HAS_INTEGRATED_BUTTON) in setup_events_to_report()
541 __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); in setup_events_to_report()
551 return -EIO; in report_bt_state()
554 "bcm5974: button data: %x %x %x %x\n", in report_bt_state()
555 dev->bt_data->unknown1, dev->bt_data->button, in report_bt_state()
556 dev->bt_data->rel_x, dev->bt_data->rel_y); in report_bt_state()
558 input_report_key(dev->input, BTN_LEFT, dev->bt_data->button); in report_bt_state()
559 input_sync(dev->input); in report_bt_state()
572 raw2int(f->touch_major) << 1); in report_finger_data()
574 raw2int(f->touch_minor) << 1); in report_finger_data()
576 raw2int(f->tool_major) << 1); in report_finger_data()
578 raw2int(f->tool_minor) << 1); in report_finger_data()
580 MAX_FINGER_ORIENTATION - raw2int(f->orientation)); in report_finger_data()
581 input_report_abs(input, ABS_MT_POSITION_X, pos->x); in report_finger_data()
582 input_report_abs(input, ABS_MT_POSITION_Y, pos->y); in report_finger_data()
592 int p = raw2int(f->touch_major); in report_synaptics_data()
593 int w = raw2int(f->tool_major); in report_synaptics_data()
594 if (p > 0 && raw2int(f->origin)) { in report_synaptics_data()
595 abs_p = clamp_val(256 * p / cfg->p.max, 0, 255); in report_synaptics_data()
596 abs_w = clamp_val(16 * w / cfg->w.max, 0, 15); in report_synaptics_data()
604 /* report trackpad data as logical trackpad state */
607 const struct bcm5974_config *c = &dev->cfg; in report_tp_state()
609 struct input_dev *input = dev->input; in report_tp_state()
612 if (size < c->tp_header || (size - c->tp_header) % c->tp_fsize != 0) in report_tp_state()
613 return -EIO; in report_tp_state()
615 raw_n = (size - c->tp_header) / c->tp_fsize; in report_tp_state()
619 if (raw2int(f->touch_major) == 0) in report_tp_state()
621 dev->pos[n].x = raw2int(f->abs_x); in report_tp_state()
622 dev->pos[n].y = c->y.min + c->y.max - raw2int(f->abs_y); in report_tp_state()
623 dev->index[n++] = f; in report_tp_state()
626 input_mt_assign_slots(input, dev->slots, dev->pos, n, 0); in report_tp_state()
629 report_finger_data(input, dev->slots[i], in report_tp_state()
630 &dev->pos[i], dev->index[i]); in report_tp_state()
637 if (c->caps & HAS_INTEGRATED_BUTTON) { in report_tp_state()
638 int ibt = raw2int(dev->tp_data[c->tp_button]); in report_tp_state()
649 const struct bcm5974_config *c = &dev->cfg; in bcm5974_wellspring_mode()
653 /* Type 3 does not require a mode switch */ in bcm5974_wellspring_mode()
654 if (c->tp_type == TYPE3) in bcm5974_wellspring_mode()
657 data = kmalloc(c->um_size, GFP_KERNEL); in bcm5974_wellspring_mode()
659 dev_err(&dev->intf->dev, "out of memory\n"); in bcm5974_wellspring_mode()
660 retval = -ENOMEM; in bcm5974_wellspring_mode()
665 size = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), in bcm5974_wellspring_mode()
668 c->um_req_val, c->um_req_idx, data, c->um_size, 5000); in bcm5974_wellspring_mode()
670 if (size != c->um_size) { in bcm5974_wellspring_mode()
671 dev_err(&dev->intf->dev, "could not read from device\n"); in bcm5974_wellspring_mode()
672 retval = -EIO; in bcm5974_wellspring_mode()
677 data[c->um_switch_idx] = on ? c->um_switch_on : c->um_switch_off; in bcm5974_wellspring_mode()
680 size = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), in bcm5974_wellspring_mode()
683 c->um_req_val, c->um_req_idx, data, c->um_size, 5000); in bcm5974_wellspring_mode()
685 if (size != c->um_size) { in bcm5974_wellspring_mode()
686 dev_err(&dev->intf->dev, "could not write to device\n"); in bcm5974_wellspring_mode()
687 retval = -EIO; in bcm5974_wellspring_mode()
701 struct bcm5974 *dev = urb->context; in bcm5974_irq_button()
702 struct usb_interface *intf = dev->intf; in bcm5974_irq_button()
705 switch (urb->status) { in bcm5974_irq_button()
708 case -EOVERFLOW: in bcm5974_irq_button()
709 case -ECONNRESET: in bcm5974_irq_button()
710 case -ENOENT: in bcm5974_irq_button()
711 case -ESHUTDOWN: in bcm5974_irq_button()
712 dev_dbg(&intf->dev, "button urb shutting down: %d\n", in bcm5974_irq_button()
713 urb->status); in bcm5974_irq_button()
716 dev_dbg(&intf->dev, "button urb status: %d\n", urb->status); in bcm5974_irq_button()
720 if (report_bt_state(dev, dev->bt_urb->actual_length)) in bcm5974_irq_button()
722 dev->bt_urb->actual_length); in bcm5974_irq_button()
725 error = usb_submit_urb(dev->bt_urb, GFP_ATOMIC); in bcm5974_irq_button()
727 dev_err(&intf->dev, "button urb failed: %d\n", error); in bcm5974_irq_button()
732 struct bcm5974 *dev = urb->context; in bcm5974_irq_trackpad()
733 struct usb_interface *intf = dev->intf; in bcm5974_irq_trackpad()
736 switch (urb->status) { in bcm5974_irq_trackpad()
739 case -EOVERFLOW: in bcm5974_irq_trackpad()
740 case -ECONNRESET: in bcm5974_irq_trackpad()
741 case -ENOENT: in bcm5974_irq_trackpad()
742 case -ESHUTDOWN: in bcm5974_irq_trackpad()
743 dev_dbg(&intf->dev, "trackpad urb shutting down: %d\n", in bcm5974_irq_trackpad()
744 urb->status); in bcm5974_irq_trackpad()
747 dev_dbg(&intf->dev, "trackpad urb status: %d\n", urb->status); in bcm5974_irq_trackpad()
752 if (dev->tp_urb->actual_length == 2) in bcm5974_irq_trackpad()
755 if (report_tp_state(dev, dev->tp_urb->actual_length)) in bcm5974_irq_trackpad()
756 dprintk(1, "bcm5974: bad trackpad package, length: %d\n", in bcm5974_irq_trackpad()
757 dev->tp_urb->actual_length); in bcm5974_irq_trackpad()
760 error = usb_submit_urb(dev->tp_urb, GFP_ATOMIC); in bcm5974_irq_trackpad()
762 dev_err(&intf->dev, "trackpad urb failed: %d\n", error); in bcm5974_irq_trackpad()
766 * The Wellspring trackpad, like many recent Apple trackpads, share
775 * device, resulting in trackpad malfunction under certain
793 if (dev->bt_urb) { in bcm5974_start_traffic()
794 error = usb_submit_urb(dev->bt_urb, GFP_KERNEL); in bcm5974_start_traffic()
799 error = usb_submit_urb(dev->tp_urb, GFP_KERNEL); in bcm5974_start_traffic()
806 usb_kill_urb(dev->bt_urb); in bcm5974_start_traffic()
815 usb_kill_urb(dev->tp_urb); in bcm5974_pause_traffic()
816 usb_kill_urb(dev->bt_urb); in bcm5974_pause_traffic()
824 * Opening a suspended device fails with EACCES - permission denied.
833 error = usb_autopm_get_interface(dev->intf); in bcm5974_open()
837 scoped_guard(mutex, &dev->pm_mutex) { in bcm5974_open()
840 dev->opened = 1; in bcm5974_open()
844 usb_autopm_put_interface(dev->intf); in bcm5974_open()
853 scoped_guard(mutex, &dev->pm_mutex) { in bcm5974_close()
855 dev->opened = 0; in bcm5974_close()
858 usb_autopm_put_interface(dev->intf); in bcm5974_close()
865 guard(mutex)(&dev->pm_mutex); in bcm5974_suspend()
867 if (dev->opened) in bcm5974_suspend()
877 guard(mutex)(&dev->pm_mutex); in bcm5974_resume()
879 if (dev->opened) in bcm5974_resume()
892 int error = -ENOMEM; in bcm5974_probe()
901 dev_err(&iface->dev, "out of memory\n"); in bcm5974_probe()
905 dev->udev = udev; in bcm5974_probe()
906 dev->intf = iface; in bcm5974_probe()
907 dev->input = input_dev; in bcm5974_probe()
908 dev->cfg = *cfg; in bcm5974_probe()
909 mutex_init(&dev->pm_mutex); in bcm5974_probe()
912 if (cfg->tp_type == TYPE1) { in bcm5974_probe()
913 dev->bt_urb = usb_alloc_urb(0, GFP_KERNEL); in bcm5974_probe()
914 if (!dev->bt_urb) in bcm5974_probe()
918 dev->tp_urb = usb_alloc_urb(0, GFP_KERNEL); in bcm5974_probe()
919 if (!dev->tp_urb) in bcm5974_probe()
922 if (dev->bt_urb) { in bcm5974_probe()
923 dev->bt_data = usb_alloc_coherent(dev->udev, in bcm5974_probe()
924 dev->cfg.bt_datalen, GFP_KERNEL, in bcm5974_probe()
925 &dev->bt_urb->transfer_dma); in bcm5974_probe()
926 if (!dev->bt_data) in bcm5974_probe()
930 dev->tp_data = usb_alloc_coherent(dev->udev, in bcm5974_probe()
931 dev->cfg.tp_datalen, GFP_KERNEL, in bcm5974_probe()
932 &dev->tp_urb->transfer_dma); in bcm5974_probe()
933 if (!dev->tp_data) in bcm5974_probe()
936 if (dev->bt_urb) { in bcm5974_probe()
937 usb_fill_int_urb(dev->bt_urb, udev, in bcm5974_probe()
938 usb_rcvintpipe(udev, cfg->bt_ep), in bcm5974_probe()
939 dev->bt_data, dev->cfg.bt_datalen, in bcm5974_probe()
942 dev->bt_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; in bcm5974_probe()
945 usb_fill_int_urb(dev->tp_urb, udev, in bcm5974_probe()
946 usb_rcvintpipe(udev, cfg->tp_ep), in bcm5974_probe()
947 dev->tp_data, dev->cfg.tp_datalen, in bcm5974_probe()
950 dev->tp_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; in bcm5974_probe()
953 usb_make_path(udev, dev->phys, sizeof(dev->phys)); in bcm5974_probe()
954 strlcat(dev->phys, "/input0", sizeof(dev->phys)); in bcm5974_probe()
956 input_dev->name = "bcm5974"; in bcm5974_probe()
957 input_dev->phys = dev->phys; in bcm5974_probe()
958 usb_to_input_id(dev->udev, &input_dev->id); in bcm5974_probe()
960 input_dev->id.version = cfg->caps; in bcm5974_probe()
961 input_dev->dev.parent = &iface->dev; in bcm5974_probe()
965 input_dev->open = bcm5974_open; in bcm5974_probe()
966 input_dev->close = bcm5974_close; in bcm5974_probe()
970 error = input_register_device(dev->input); in bcm5974_probe()
980 usb_free_coherent(dev->udev, dev->cfg.tp_datalen, in bcm5974_probe()
981 dev->tp_data, dev->tp_urb->transfer_dma); in bcm5974_probe()
983 if (dev->bt_urb) in bcm5974_probe()
984 usb_free_coherent(dev->udev, dev->cfg.bt_datalen, in bcm5974_probe()
985 dev->bt_data, dev->bt_urb->transfer_dma); in bcm5974_probe()
987 usb_free_urb(dev->tp_urb); in bcm5974_probe()
989 usb_free_urb(dev->bt_urb); in bcm5974_probe()
1003 input_unregister_device(dev->input); in bcm5974_disconnect()
1004 usb_free_coherent(dev->udev, dev->cfg.tp_datalen, in bcm5974_disconnect()
1005 dev->tp_data, dev->tp_urb->transfer_dma); in bcm5974_disconnect()
1006 if (dev->bt_urb) in bcm5974_disconnect()
1007 usb_free_coherent(dev->udev, dev->cfg.bt_datalen, in bcm5974_disconnect()
1008 dev->bt_data, dev->bt_urb->transfer_dma); in bcm5974_disconnect()
1009 usb_free_urb(dev->tp_urb); in bcm5974_disconnect()
1010 usb_free_urb(dev->bt_urb); in bcm5974_disconnect()