File Index
Files and directories
Sign in
FILE

hid-magicmouse.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hid/hid-magicmouse.c C
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *   Apple "Magic" Wireless Mouse driver
   4 *
   5 *   Copyright (c) 2010 Michael Poole <mdpoole@troilus.org>
   6 *   Copyright (c) 2010 Chase Douglas <chase.douglas@canonical.com>
   7 */
   8
   9/*
  10 */
  11
  12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  13
  14#include <linux/device.h>
  15#include <linux/hid.h>
  16#include <linux/input/mt.h>
  17#include <linux/module.h>
  18#include <linux/slab.h>
  19#include <linux/workqueue.h>
  20
  21#include "hid-ids.h"
  22
  23static bool emulate_3button = true;
  24module_param(emulate_3button, bool, 0644);
  25MODULE_PARM_DESC(emulate_3button, "Emulate a middle button");
  26
  27static int middle_button_start = -350;
  28static int middle_button_stop = +350;
  29
  30static bool emulate_scroll_wheel = true;
  31module_param(emulate_scroll_wheel, bool, 0644);
  32MODULE_PARM_DESC(emulate_scroll_wheel, "Emulate a scroll wheel");
  33
  34static unsigned int scroll_speed = 32;
  35static int param_set_scroll_speed(const char *val,
  36				  const struct kernel_param *kp) {
  37	unsigned long speed;
  38	if (!val || kstrtoul(val, 0, &speed) || speed > 63)
  39		return -EINVAL;
  40	scroll_speed = speed;
  41	return 0;
  42}
  43module_param_call(scroll_speed, param_set_scroll_speed, param_get_uint, &scroll_speed, 0644);
  44MODULE_PARM_DESC(scroll_speed, "Scroll speed, value from 0 (slow) to 63 (fast)");
  45
  46static bool scroll_acceleration = false;
  47module_param(scroll_acceleration, bool, 0644);
  48MODULE_PARM_DESC(scroll_acceleration, "Accelerate sequential scroll events");
  49
  50static bool report_undeciphered;
  51module_param(report_undeciphered, bool, 0644);
  52MODULE_PARM_DESC(report_undeciphered, "Report undeciphered multi-touch state field using a MSC_RAW event");
  53
  54#define TRACKPAD2_2021_BT_VERSION 0x110
  55#define TRACKPAD_2024_BT_VERSION 0x314
  56
  57#define TRACKPAD_REPORT_ID 0x28
  58#define TRACKPAD2_USB_REPORT_ID 0x02
  59#define TRACKPAD2_BT_REPORT_ID 0x31
  60#define MOUSE_REPORT_ID    0x29
  61#define MOUSE2_REPORT_ID   0x12
  62#define DOUBLE_REPORT_ID   0xf7
  63#define USB_BATTERY_TIMEOUT_SEC 60
  64
  65/* These definitions are not precise, but they're close enough.  (Bits
  66 * 0x03 seem to indicate the aspect ratio of the touch, bits 0x70 seem
  67 * to be some kind of bit mask -- 0x20 may be a near-field reading,
  68 * and 0x40 is actual contact, and 0x10 may be a start/stop or change
  69 * indication.)
  70 */
  71#define TOUCH_STATE_MASK  0xf0
  72#define TOUCH_STATE_NONE  0x00
  73#define TOUCH_STATE_START 0x30
  74#define TOUCH_STATE_DRAG  0x40
  75
  76/* Number of high-resolution events for each low-resolution detent. */
  77#define SCROLL_HR_STEPS 10
  78#define SCROLL_HR_MULT (120 / SCROLL_HR_STEPS)
  79#define SCROLL_HR_THRESHOLD 90 /* units */
  80#define SCROLL_ACCEL_DEFAULT 7
  81
  82/* Touch surface information. Dimension is in hundredths of a mm, min and max
  83 * are in units. */
  84#define MOUSE_DIMENSION_X (float)9056
  85#define MOUSE_MIN_X -1100
  86#define MOUSE_MAX_X 1258
  87#define MOUSE_RES_X ((MOUSE_MAX_X - MOUSE_MIN_X) / (MOUSE_DIMENSION_X / 100))
  88#define MOUSE_DIMENSION_Y (float)5152
  89#define MOUSE_MIN_Y -1589
  90#define MOUSE_MAX_Y 2047
  91#define MOUSE_RES_Y ((MOUSE_MAX_Y - MOUSE_MIN_Y) / (MOUSE_DIMENSION_Y / 100))
  92
  93#define TRACKPAD_DIMENSION_X (float)13000
  94#define TRACKPAD_MIN_X -2909
  95#define TRACKPAD_MAX_X 3167
  96#define TRACKPAD_RES_X \
  97	((TRACKPAD_MAX_X - TRACKPAD_MIN_X) / (TRACKPAD_DIMENSION_X / 100))
  98#define TRACKPAD_DIMENSION_Y (float)11000
  99#define TRACKPAD_MIN_Y -2456
 100#define TRACKPAD_MAX_Y 2565
 101#define TRACKPAD_RES_Y \
 102	((TRACKPAD_MAX_Y - TRACKPAD_MIN_Y) / (TRACKPAD_DIMENSION_Y / 100))
 103
 104#define TRACKPAD2_DIMENSION_X (float)16000
 105#define TRACKPAD2_MIN_X -3678
 106#define TRACKPAD2_MAX_X 3934
 107#define TRACKPAD2_RES_X \
 108	((TRACKPAD2_MAX_X - TRACKPAD2_MIN_X) / (TRACKPAD2_DIMENSION_X / 100))
 109#define TRACKPAD2_DIMENSION_Y (float)11490
 110#define TRACKPAD2_MIN_Y -2478
 111#define TRACKPAD2_MAX_Y 2587
 112#define TRACKPAD2_RES_Y \
 113	((TRACKPAD2_MAX_Y - TRACKPAD2_MIN_Y) / (TRACKPAD2_DIMENSION_Y / 100))
 114
 115/**
 116 * struct magicmouse_sc - Tracks Magic Mouse-specific data.
 117 * @input: Input device through which we report events.
 118 * @quirks: Currently unused.
 119 * @ntouches: Number of touches in most recent touch report.
 120 * @scroll_accel: Number of consecutive scroll motions.
 121 * @scroll_jiffies: Time of last scroll motion.
 122 * @touches: Most recent data for a touch, indexed by tracking ID.
 123 * @tracking_ids: Mapping of current touch input data to @touches.
 124 * @hdev: Pointer to the underlying HID device.
 125 * @work: Workqueue to handle initialization retry for quirky devices.
 126 * @battery_timer: Timer for obtaining battery level information.
 127 */
 128struct magicmouse_sc {
 129	struct input_dev *input;
 130	unsigned long quirks;
 131
 132	int ntouches;
 133	int scroll_accel;
 134	unsigned long scroll_jiffies;
 135
 136	struct {
 137		short x;
 138		short y;
 139		short scroll_x;
 140		short scroll_y;
 141		short scroll_x_hr;
 142		short scroll_y_hr;
 143		u8 size;
 144		bool scroll_x_active;
 145		bool scroll_y_active;
 146	} touches[16];
 147	int tracking_ids[16];
 148
 149	struct hid_device *hdev;
 150	struct delayed_work work;
 151	struct timer_list battery_timer;
 152};
 153
 154static int magicmouse_firm_touch(struct magicmouse_sc *msc)
 155{
 156	int touch = -1;
 157	int ii;
 158
 159	/* If there is only one "firm" touch, set touch to its
 160	 * tracking ID.
 161	 */
 162	for (ii = 0; ii < msc->ntouches; ii++) {
 163		int idx = msc->tracking_ids[ii];
 164		if (msc->touches[idx].size < 8) {
 165			/* Ignore this touch. */
 166		} else if (touch >= 0) {
 167			touch = -1;
 168			break;
 169		} else {
 170			touch = idx;
 171		}
 172	}
 173
 174	return touch;
 175}
 176
 177static void magicmouse_emit_buttons(struct magicmouse_sc *msc, int state)
 178{
 179	int last_state = test_bit(BTN_LEFT, msc->input->key) << 0 |
 180		test_bit(BTN_RIGHT, msc->input->key) << 1 |
 181		test_bit(BTN_MIDDLE, msc->input->key) << 2;
 182
 183	if (emulate_3button) {
 184		int id;
 185
 186		/* If some button was pressed before, keep it held
 187		 * down.  Otherwise, if there's exactly one firm
 188		 * touch, use that to override the mouse's guess.
 189		 */
 190		if (state == 0) {
 191			/* The button was released. */
 192		} else if (last_state != 0) {
 193			state = last_state;
 194		} else if ((id = magicmouse_firm_touch(msc)) >= 0) {
 195			int x = msc->touches[id].x;
 196			if (x < middle_button_start)
 197				state = 1;
 198			else if (x > middle_button_stop)
 199				state = 2;
 200			else
 201				state = 4;
 202		} /* else: we keep the mouse's guess */
 203
 204		input_report_key(msc->input, BTN_MIDDLE, state & 4);
 205	}
 206
 207	input_report_key(msc->input, BTN_LEFT, state & 1);
 208	input_report_key(msc->input, BTN_RIGHT, state & 2);
 209
 210	if (state != last_state)
 211		msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
 212}
 213
 214static void magicmouse_emit_touch(struct magicmouse_sc *msc, int raw_id, u8 *tdata)
 215{
 216	struct input_dev *input = msc->input;
 217	int id, x, y, size, orientation, touch_major, touch_minor, state, down;
 218	int pressure = 0;
 219
 220	if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
 221	    input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
 222	    input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC) {
 223		id = (tdata[6] << 2 | tdata[5] >> 6) & 0xf;
 224		x = (tdata[1] << 28 | tdata[0] << 20) >> 20;
 225		y = -((tdata[2] << 24 | tdata[1] << 16) >> 20);
 226		size = tdata[5] & 0x3f;
 227		orientation = (tdata[6] >> 2) - 32;
 228		touch_major = tdata[3];
 229		touch_minor = tdata[4];
 230		state = tdata[7] & TOUCH_STATE_MASK;
 231		down = state != TOUCH_STATE_NONE;
 232	} else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
 233		   input->id.product ==
 234			   USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
 235		id = tdata[8] & 0xf;
 236		x = (tdata[1] << 27 | tdata[0] << 19) >> 19;
 237		y = -((tdata[3] << 30 | tdata[2] << 22 | tdata[1] << 14) >> 19);
 238		size = tdata[6];
 239		orientation = (tdata[8] >> 5) - 4;
 240		touch_major = tdata[4];
 241		touch_minor = tdata[5];
 242		pressure = tdata[7];
 243		state = tdata[3] & 0xC0;
 244		down = state == 0x80;
 245	} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
 246		id = (tdata[7] << 2 | tdata[6] >> 6) & 0xf;
 247		x = (tdata[1] << 27 | tdata[0] << 19) >> 19;
 248		y = -((tdata[3] << 30 | tdata[2] << 22 | tdata[1] << 14) >> 19);
 249		size = tdata[6] & 0x3f;
 250		orientation = (tdata[7] >> 2) - 32;
 251		touch_major = tdata[4];
 252		touch_minor = tdata[5];
 253		state = tdata[8] & TOUCH_STATE_MASK;
 254		down = state != TOUCH_STATE_NONE;
 255	}
 256
 257	/* Store tracking ID and other fields. */
 258	msc->tracking_ids[raw_id] = id;
 259	msc->touches[id].x = x;
 260	msc->touches[id].y = y;
 261	msc->touches[id].size = size;
 262
 263	/* If requested, emulate a scroll wheel by detecting small
 264	 * vertical touch motions.
 265	 */
 266	if (emulate_scroll_wheel &&
 267	    input->id.product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
 268	    input->id.product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
 269		unsigned long now = jiffies;
 270		int step_x = msc->touches[id].scroll_x - x;
 271		int step_y = msc->touches[id].scroll_y - y;
 272		int step_hr =
 273			max_t(int,
 274			      ((64 - (int)scroll_speed) * msc->scroll_accel) /
 275					SCROLL_HR_STEPS,
 276			      1);
 277		int step_x_hr = msc->touches[id].scroll_x_hr - x;
 278		int step_y_hr = msc->touches[id].scroll_y_hr - y;
 279
 280		/* Calculate and apply the scroll motion. */
 281		switch (state) {
 282		case TOUCH_STATE_START:
 283			msc->touches[id].scroll_x = x;
 284			msc->touches[id].scroll_y = y;
 285			msc->touches[id].scroll_x_hr = x;
 286			msc->touches[id].scroll_y_hr = y;
 287			msc->touches[id].scroll_x_active = false;
 288			msc->touches[id].scroll_y_active = false;
 289
 290			/* Reset acceleration after half a second. */
 291			if (scroll_acceleration && time_before(now,
 292						msc->scroll_jiffies + HZ / 2))
 293				msc->scroll_accel = max_t(int,
 294						msc->scroll_accel - 1, 1);
 295			else
 296				msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
 297
 298			break;
 299		case TOUCH_STATE_DRAG:
 300			step_x /= (64 - (int)scroll_speed) * msc->scroll_accel;
 301			if (step_x != 0) {
 302				msc->touches[id].scroll_x -= step_x *
 303					(64 - scroll_speed) * msc->scroll_accel;
 304				msc->scroll_jiffies = now;
 305				input_report_rel(input, REL_HWHEEL, -step_x);
 306			}
 307
 308			step_y /= (64 - (int)scroll_speed) * msc->scroll_accel;
 309			if (step_y != 0) {
 310				msc->touches[id].scroll_y -= step_y *
 311					(64 - scroll_speed) * msc->scroll_accel;
 312				msc->scroll_jiffies = now;
 313				input_report_rel(input, REL_WHEEL, step_y);
 314			}
 315
 316			if (!msc->touches[id].scroll_x_active &&
 317			    abs(step_x_hr) > SCROLL_HR_THRESHOLD) {
 318				msc->touches[id].scroll_x_active = true;
 319				msc->touches[id].scroll_x_hr = x;
 320				step_x_hr = 0;
 321			}
 322
 323			step_x_hr /= step_hr;
 324			if (step_x_hr != 0 &&
 325			    msc->touches[id].scroll_x_active) {
 326				msc->touches[id].scroll_x_hr -= step_x_hr *
 327					step_hr;
 328				input_report_rel(input,
 329						 REL_HWHEEL_HI_RES,
 330						 -step_x_hr * SCROLL_HR_MULT);
 331			}
 332
 333			if (!msc->touches[id].scroll_y_active &&
 334			    abs(step_y_hr) > SCROLL_HR_THRESHOLD) {
 335				msc->touches[id].scroll_y_active = true;
 336				msc->touches[id].scroll_y_hr = y;
 337				step_y_hr = 0;
 338			}
 339
 340			step_y_hr /= step_hr;
 341			if (step_y_hr != 0 &&
 342			    msc->touches[id].scroll_y_active) {
 343				msc->touches[id].scroll_y_hr -= step_y_hr *
 344					step_hr;
 345				input_report_rel(input,
 346						 REL_WHEEL_HI_RES,
 347						 step_y_hr * SCROLL_HR_MULT);
 348			}
 349			break;
 350		}
 351	}
 352
 353	if (down)
 354		msc->ntouches++;
 355
 356	input_mt_slot(input, id);
 357	input_mt_report_slot_state(input, MT_TOOL_FINGER, down);
 358
 359	/* Generate the input events for this touch. */
 360	if (down) {
 361		input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2);
 362		input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2);
 363		input_report_abs(input, ABS_MT_ORIENTATION, -orientation);
 364		input_report_abs(input, ABS_MT_POSITION_X, x);
 365		input_report_abs(input, ABS_MT_POSITION_Y, y);
 366
 367		if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
 368		    input->id.product ==
 369			    USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC)
 370			input_report_abs(input, ABS_MT_PRESSURE, pressure);
 371
 372		if (report_undeciphered) {
 373			if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
 374			    input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
 375			    input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC)
 376				input_event(input, EV_MSC, MSC_RAW, tdata[7]);
 377			else if (input->id.product !=
 378					 USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
 379				 input->id.product !=
 380					 USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC)
 381				input_event(input, EV_MSC, MSC_RAW, tdata[8]);
 382		}
 383	}
 384}
 385
 386static int magicmouse_raw_event(struct hid_device *hdev,
 387		struct hid_report *report, u8 *data, int size)
 388{
 389	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
 390	struct input_dev *input = msc->input;
 391	int x = 0, y = 0, ii, clicks = 0, npoints;
 392
 393	switch (data[0]) {
 394	case TRACKPAD_REPORT_ID:
 395	case TRACKPAD2_BT_REPORT_ID:
 396		/* Expect four bytes of prefix, and N*9 bytes of touch data. */
 397		if (size < 4 || ((size - 4) % 9) != 0)
 398			return 0;
 399		npoints = (size - 4) / 9;
 400		if (npoints > 15) {
 401			hid_warn(hdev, "invalid size value (%d) for TRACKPAD_REPORT_ID\n",
 402					size);
 403			return 0;
 404		}
 405		msc->ntouches = 0;
 406		for (ii = 0; ii < npoints; ii++)
 407			magicmouse_emit_touch(msc, ii, data + ii * 9 + 4);
 408
 409		clicks = data[1];
 410
 411		/* The following bits provide a device specific timestamp. They
 412		 * are unused here.
 413		 *
 414		 * ts = data[1] >> 6 | data[2] << 2 | data[3] << 10;
 415		 */
 416		break;
 417	case TRACKPAD2_USB_REPORT_ID:
 418		/* Expect twelve bytes of prefix and N*9 bytes of touch data. */
 419		if (size < 12 || ((size - 12) % 9) != 0)
 420			return 0;
 421		npoints = (size - 12) / 9;
 422		if (npoints > 15) {
 423			hid_warn(hdev, "invalid size value (%d) for TRACKPAD2_USB_REPORT_ID\n",
 424					size);
 425			return 0;
 426		}
 427		msc->ntouches = 0;
 428		for (ii = 0; ii < npoints; ii++)
 429			magicmouse_emit_touch(msc, ii, data + ii * 9 + 12);
 430
 431		clicks = data[1];
 432		break;
 433	case MOUSE_REPORT_ID:
 434		/* Expect six bytes of prefix, and N*8 bytes of touch data. */
 435		if (size < 6 || ((size - 6) % 8) != 0)
 436			return 0;
 437		npoints = (size - 6) / 8;
 438		if (npoints > 15) {
 439			hid_warn(hdev, "invalid size value (%d) for MOUSE_REPORT_ID\n",
 440					size);
 441			return 0;
 442		}
 443		msc->ntouches = 0;
 444		for (ii = 0; ii < npoints; ii++)
 445			magicmouse_emit_touch(msc, ii, data + ii * 8 + 6);
 446
 447		/* When emulating three-button mode, it is important
 448		 * to have the current touch information before
 449		 * generating a click event.
 450		 */
 451		x = (int)(((data[3] & 0x0c) << 28) | (data[1] << 22)) >> 22;
 452		y = (int)(((data[3] & 0x30) << 26) | (data[2] << 22)) >> 22;
 453		clicks = data[3];
 454
 455		/* The following bits provide a device specific timestamp. They
 456		 * are unused here.
 457		 *
 458		 * ts = data[3] >> 6 | data[4] << 2 | data[5] << 10;
 459		 */
 460		break;
 461	case MOUSE2_REPORT_ID:
 462		/* Size is either 8 or (14 + 8 * N) */
 463		if (size != 8 && (size < 14 || (size - 14) % 8 != 0))
 464			return 0;
 465		npoints = (size - 14) / 8;
 466		if (npoints > 15) {
 467			hid_warn(hdev, "invalid size value (%d) for MOUSE2_REPORT_ID\n",
 468					size);
 469			return 0;
 470		}
 471		msc->ntouches = 0;
 472		for (ii = 0; ii < npoints; ii++)
 473			magicmouse_emit_touch(msc, ii, data + ii * 8 + 14);
 474
 475		/* When emulating three-button mode, it is important
 476		 * to have the current touch information before
 477		 * generating a click event.
 478		 */
 479		x = (int)((data[3] << 24) | (data[2] << 16)) >> 16;
 480		y = (int)((data[5] << 24) | (data[4] << 16)) >> 16;
 481		clicks = data[1];
 482
 483		/* The following bits provide a device specific timestamp. They
 484		 * are unused here.
 485		 *
 486		 * ts = data[11] >> 6 | data[12] << 2 | data[13] << 10;
 487		 */
 488		break;
 489	case DOUBLE_REPORT_ID:
 490		/* Sometimes the trackpad sends two touch reports in one
 491		 * packet.
 492		 */
 493		magicmouse_raw_event(hdev, report, data + 2, data[1]);
 494		magicmouse_raw_event(hdev, report, data + 2 + data[1],
 495			size - 2 - data[1]);
 496		return 0;
 497	default:
 498		return 0;
 499	}
 500
 501	if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
 502	    input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
 503	    input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC) {
 504		magicmouse_emit_buttons(msc, clicks & 3);
 505		input_report_rel(input, REL_X, x);
 506		input_report_rel(input, REL_Y, y);
 507	} else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
 508		   input->id.product ==
 509			   USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
 510		input_mt_sync_frame(input);
 511		input_report_key(input, BTN_MOUSE, clicks & 1);
 512	} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
 513		input_report_key(input, BTN_MOUSE, clicks & 1);
 514		input_mt_report_pointer_emulation(input, true);
 515	}
 516
 517	input_sync(input);
 518	return 1;
 519}
 520
 521static int magicmouse_event(struct hid_device *hdev, struct hid_field *field,
 522		struct hid_usage *usage, __s32 value)
 523{
 524	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
 525	if ((msc->input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
 526	     msc->input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC) &&
 527	    field->report->id == MOUSE2_REPORT_ID) {
 528		/*
 529		 * magic_mouse_raw_event has done all the work. Skip hidinput.
 530		 *
 531		 * Specifically, hidinput may modify BTN_LEFT and BTN_RIGHT,
 532		 * breaking emulate_3button.
 533		 */
 534		return 1;
 535	}
 536	return 0;
 537}
 538
 539static int magicmouse_setup_input(struct input_dev *input, struct hid_device *hdev)
 540{
 541	int error;
 542	int mt_flags = 0;
 543
 544	__set_bit(EV_KEY, input->evbit);
 545
 546	if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
 547	    input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
 548	    input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC) {
 549		__set_bit(BTN_LEFT, input->keybit);
 550		__set_bit(BTN_RIGHT, input->keybit);
 551		if (emulate_3button)
 552			__set_bit(BTN_MIDDLE, input->keybit);
 553
 554		__set_bit(EV_REL, input->evbit);
 555		__set_bit(REL_X, input->relbit);
 556		__set_bit(REL_Y, input->relbit);
 557		if (emulate_scroll_wheel) {
 558			__set_bit(REL_WHEEL, input->relbit);
 559			__set_bit(REL_HWHEEL, input->relbit);
 560			__set_bit(REL_WHEEL_HI_RES, input->relbit);
 561			__set_bit(REL_HWHEEL_HI_RES, input->relbit);
 562		}
 563	} else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
 564		   input->id.product ==
 565			   USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
 566		/* If the trackpad has been connected to a Mac, the name is
 567		 * automatically personalized, e.g., "José Expósito's Trackpad".
 568		 * When connected through Bluetooth, the personalized name is
 569		 * reported, however, when connected through USB the generic
 570		 * name is reported.
 571		 * Set the device name to ensure the same driver settings get
 572		 * loaded, whether connected through bluetooth or USB.
 573		 */
 574		if (hdev->vendor == BT_VENDOR_ID_APPLE) {
 575			if (input->id.version == TRACKPAD2_2021_BT_VERSION)
 576				input->name = "Apple Inc. Magic Trackpad 2021";
 577			else if (input->id.version == TRACKPAD_2024_BT_VERSION) {
 578				input->name = "Apple Inc. Magic Trackpad USB-C";
 579			} else {
 580				input->name = "Apple Inc. Magic Trackpad";
 581			}
 582		} else { /* USB_VENDOR_ID_APPLE */
 583			input->name = hdev->name;
 584		}
 585
 586		__clear_bit(EV_MSC, input->evbit);
 587		__clear_bit(BTN_0, input->keybit);
 588		__clear_bit(BTN_RIGHT, input->keybit);
 589		__clear_bit(BTN_MIDDLE, input->keybit);
 590		__set_bit(BTN_MOUSE, input->keybit);
 591		__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
 592		__set_bit(BTN_TOOL_FINGER, input->keybit);
 593
 594		mt_flags = INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED |
 595				INPUT_MT_TRACK;
 596	} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
 597		/* input->keybit is initialized with incorrect button info
 598		 * for Magic Trackpad. There really is only one physical
 599		 * button (BTN_LEFT == BTN_MOUSE). Make sure we don't
 600		 * advertise buttons that don't exist...
 601		 */
 602		__clear_bit(BTN_RIGHT, input->keybit);
 603		__clear_bit(BTN_MIDDLE, input->keybit);
 604		__set_bit(BTN_MOUSE, input->keybit);
 605		__set_bit(BTN_TOOL_FINGER, input->keybit);
 606		__set_bit(BTN_TOOL_DOUBLETAP, input->keybit);
 607		__set_bit(BTN_TOOL_TRIPLETAP, input->keybit);
 608		__set_bit(BTN_TOOL_QUADTAP, input->keybit);
 609		__set_bit(BTN_TOOL_QUINTTAP, input->keybit);
 610		__set_bit(BTN_TOUCH, input->keybit);
 611		__set_bit(INPUT_PROP_POINTER, input->propbit);
 612		__set_bit(INPUT_PROP_BUTTONPAD, input->propbit);
 613	}
 614
 615
 616	__set_bit(EV_ABS, input->evbit);
 617
 618	error = input_mt_init_slots(input, 16, mt_flags);
 619	if (error)
 620		return error;
 621	input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255 << 2,
 622			     4, 0);
 623	input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255 << 2,
 624			     4, 0);
 625
 626	/* Note: Touch Y position from the device is inverted relative
 627	 * to how pointer motion is reported (and relative to how USB
 628	 * HID recommends the coordinates work).  This driver keeps
 629	 * the origin at the same position, and just uses the additive
 630	 * inverse of the reported Y.
 631	 */
 632	if (input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE ||
 633	    input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
 634	    input->id.product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC) {
 635		input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0);
 636		input_set_abs_params(input, ABS_MT_POSITION_X,
 637				     MOUSE_MIN_X, MOUSE_MAX_X, 4, 0);
 638		input_set_abs_params(input, ABS_MT_POSITION_Y,
 639				     MOUSE_MIN_Y, MOUSE_MAX_Y, 4, 0);
 640
 641		input_abs_set_res(input, ABS_MT_POSITION_X,
 642				  MOUSE_RES_X);
 643		input_abs_set_res(input, ABS_MT_POSITION_Y,
 644				  MOUSE_RES_Y);
 645	} else if (input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
 646		   input->id.product ==
 647			   USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
 648		input_set_abs_params(input, ABS_MT_PRESSURE, 0, 253, 0, 0);
 649		input_set_abs_params(input, ABS_PRESSURE, 0, 253, 0, 0);
 650		input_set_abs_params(input, ABS_MT_ORIENTATION, -3, 4, 0, 0);
 651		input_set_abs_params(input, ABS_X, TRACKPAD2_MIN_X,
 652				     TRACKPAD2_MAX_X, 0, 0);
 653		input_set_abs_params(input, ABS_Y, TRACKPAD2_MIN_Y,
 654				     TRACKPAD2_MAX_Y, 0, 0);
 655		input_set_abs_params(input, ABS_MT_POSITION_X,
 656				     TRACKPAD2_MIN_X, TRACKPAD2_MAX_X, 0, 0);
 657		input_set_abs_params(input, ABS_MT_POSITION_Y,
 658				     TRACKPAD2_MIN_Y, TRACKPAD2_MAX_Y, 0, 0);
 659
 660		input_abs_set_res(input, ABS_X, TRACKPAD2_RES_X);
 661		input_abs_set_res(input, ABS_Y, TRACKPAD2_RES_Y);
 662		input_abs_set_res(input, ABS_MT_POSITION_X, TRACKPAD2_RES_X);
 663		input_abs_set_res(input, ABS_MT_POSITION_Y, TRACKPAD2_RES_Y);
 664	} else { /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
 665		input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0);
 666		input_set_abs_params(input, ABS_X, TRACKPAD_MIN_X,
 667				     TRACKPAD_MAX_X, 4, 0);
 668		input_set_abs_params(input, ABS_Y, TRACKPAD_MIN_Y,
 669				     TRACKPAD_MAX_Y, 4, 0);
 670		input_set_abs_params(input, ABS_MT_POSITION_X,
 671				     TRACKPAD_MIN_X, TRACKPAD_MAX_X, 4, 0);
 672		input_set_abs_params(input, ABS_MT_POSITION_Y,
 673				     TRACKPAD_MIN_Y, TRACKPAD_MAX_Y, 4, 0);
 674
 675		input_abs_set_res(input, ABS_X, TRACKPAD_RES_X);
 676		input_abs_set_res(input, ABS_Y, TRACKPAD_RES_Y);
 677		input_abs_set_res(input, ABS_MT_POSITION_X,
 678				  TRACKPAD_RES_X);
 679		input_abs_set_res(input, ABS_MT_POSITION_Y,
 680				  TRACKPAD_RES_Y);
 681	}
 682
 683	input_set_events_per_packet(input, 60);
 684
 685	if (report_undeciphered &&
 686	    input->id.product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 &&
 687	    input->id.product != USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) {
 688		__set_bit(EV_MSC, input->evbit);
 689		__set_bit(MSC_RAW, input->mscbit);
 690	}
 691
 692	/*
 693	 * hid-input may mark device as using autorepeat, but neither
 694	 * the trackpad, nor the mouse actually want it.
 695	 */
 696	__clear_bit(EV_REP, input->evbit);
 697
 698	return 0;
 699}
 700
 701static int magicmouse_input_mapping(struct hid_device *hdev,
 702		struct hid_input *hi, struct hid_field *field,
 703		struct hid_usage *usage, unsigned long **bit, int *max)
 704{
 705	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
 706
 707	if (!msc->input)
 708		msc->input = hi->input;
 709
 710	/* Magic Trackpad does not give relative data after switching to MT */
 711	if ((hi->input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD ||
 712	     hi->input->id.product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
 713	     hi->input->id.product ==
 714		     USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC) &&
 715	    field->flags & HID_MAIN_ITEM_RELATIVE)
 716		return -1;
 717
 718	return 0;
 719}
 720
 721static int magicmouse_input_configured(struct hid_device *hdev,
 722		struct hid_input *hi)
 723
 724{
 725	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
 726	int ret;
 727
 728	if (!msc->input) {
 729		hid_err(hdev, "magicmouse setup input failed (no input)");
 730		return -EINVAL;
 731	}
 732
 733	ret = magicmouse_setup_input(msc->input, hdev);
 734	if (ret) {
 735		hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
 736		/* clean msc->input to notify probe() of the failure */
 737		msc->input = NULL;
 738		return ret;
 739	}
 740
 741	return 0;
 742}
 743
 744static int magicmouse_enable_multitouch(struct hid_device *hdev)
 745{
 746	const u8 *feature;
 747	const u8 feature_mt[] = { 0xD7, 0x01 };
 748	const u8 feature_mt_mouse2[] = { 0xF1, 0x02, 0x01 };
 749	const u8 feature_mt_trackpad2_usb[] = { 0x02, 0x01 };
 750	const u8 feature_mt_trackpad2_bt[] = { 0xF1, 0x02, 0x01 };
 751	u8 *buf;
 752	int ret;
 753	int feature_size;
 754
 755	switch (hdev->product) {
 756	case USB_DEVICE_ID_APPLE_MAGICTRACKPAD2:
 757	case USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC:
 758		switch (hdev->vendor) {
 759		case BT_VENDOR_ID_APPLE:
 760			feature_size = sizeof(feature_mt_trackpad2_bt);
 761			feature = feature_mt_trackpad2_bt;
 762			break;
 763		default: /* USB_VENDOR_ID_APPLE */
 764			feature_size = sizeof(feature_mt_trackpad2_usb);
 765			feature = feature_mt_trackpad2_usb;
 766		}
 767		break;
 768	case USB_DEVICE_ID_APPLE_MAGICMOUSE2:
 769	case USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC:
 770		feature_size = sizeof(feature_mt_mouse2);
 771		feature = feature_mt_mouse2;
 772		break;
 773	default:
 774		feature_size = sizeof(feature_mt);
 775		feature = feature_mt;
 776	}
 777
 778	buf = kmemdup(feature, feature_size, GFP_KERNEL);
 779	if (!buf)
 780		return -ENOMEM;
 781
 782	ret = hid_hw_raw_request(hdev, buf[0], buf, feature_size,
 783				HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
 784	kfree(buf);
 785	return ret;
 786}
 787
 788static void magicmouse_enable_mt_work(struct work_struct *work)
 789{
 790	struct magicmouse_sc *msc =
 791		container_of(work, struct magicmouse_sc, work.work);
 792	int ret;
 793
 794	ret = magicmouse_enable_multitouch(msc->hdev);
 795	if (ret < 0)
 796		hid_err(msc->hdev, "unable to request touch data (%d)\n", ret);
 797}
 798
 799static bool is_usb_magicmouse2(__u32 vendor, __u32 product)
 800{
 801	if (vendor != USB_VENDOR_ID_APPLE)
 802		return false;
 803	return product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
 804	       product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC;
 805}
 806
 807static bool is_usb_magictrackpad2(__u32 vendor, __u32 product)
 808{
 809	if (vendor != USB_VENDOR_ID_APPLE)
 810		return false;
 811	return product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2 ||
 812	       product == USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC;
 813}
 814
 815static int magicmouse_fetch_battery(struct hid_device *hdev)
 816{
 817#ifdef CONFIG_HID_BATTERY_STRENGTH
 818	struct hid_report_enum *report_enum;
 819	struct hid_report *report;
 820
 821	if (!hdev->battery ||
 822	    (!is_usb_magicmouse2(hdev->vendor, hdev->product) &&
 823	     !is_usb_magictrackpad2(hdev->vendor, hdev->product)))
 824		return -1;
 825
 826	report_enum = &hdev->report_enum[hdev->battery_report_type];
 827	report = report_enum->report_id_hash[hdev->battery_report_id];
 828
 829	if (!report || report->maxfield < 1)
 830		return -1;
 831
 832	if (hdev->battery_capacity == hdev->battery_max)
 833		return -1;
 834
 835	hid_hw_request(hdev, report, HID_REQ_GET_REPORT);
 836	return 0;
 837#else
 838	return -1;
 839#endif
 840}
 841
 842static void magicmouse_battery_timer_tick(struct timer_list *t)
 843{
 844	struct magicmouse_sc *msc = timer_container_of(msc, t, battery_timer);
 845	struct hid_device *hdev = msc->hdev;
 846
 847	if (magicmouse_fetch_battery(hdev) == 0) {
 848		mod_timer(&msc->battery_timer,
 849			  jiffies + secs_to_jiffies(USB_BATTERY_TIMEOUT_SEC));
 850	}
 851}
 852
 853static int magicmouse_probe(struct hid_device *hdev,
 854	const struct hid_device_id *id)
 855{
 856	struct magicmouse_sc *msc;
 857	struct hid_report *report;
 858	int ret;
 859
 860	msc = devm_kzalloc(&hdev->dev, sizeof(*msc), GFP_KERNEL);
 861	if (msc == NULL) {
 862		hid_err(hdev, "can't alloc magicmouse descriptor\n");
 863		return -ENOMEM;
 864	}
 865
 866	msc->scroll_accel = SCROLL_ACCEL_DEFAULT;
 867	msc->hdev = hdev;
 868	INIT_DEFERRABLE_WORK(&msc->work, magicmouse_enable_mt_work);
 869
 870	msc->quirks = id->driver_data;
 871	hid_set_drvdata(hdev, msc);
 872
 873	ret = hid_parse(hdev);
 874	if (ret) {
 875		hid_err(hdev, "magicmouse hid parse failed\n");
 876		return ret;
 877	}
 878
 879	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 880	if (ret) {
 881		hid_err(hdev, "magicmouse hw start failed\n");
 882		return ret;
 883	}
 884
 885	if (is_usb_magicmouse2(id->vendor, id->product) ||
 886	    is_usb_magictrackpad2(id->vendor, id->product)) {
 887		timer_setup(&msc->battery_timer, magicmouse_battery_timer_tick, 0);
 888		mod_timer(&msc->battery_timer,
 889			  jiffies + secs_to_jiffies(USB_BATTERY_TIMEOUT_SEC));
 890		magicmouse_fetch_battery(hdev);
 891	}
 892
 893	if (is_usb_magicmouse2(id->vendor, id->product) ||
 894	    (is_usb_magictrackpad2(id->vendor, id->product) &&
 895	     hdev->type != HID_TYPE_USBMOUSE))
 896		return 0;
 897
 898	if (!msc->input) {
 899		hid_err(hdev, "magicmouse input not registered\n");
 900		ret = -ENOMEM;
 901		goto err_stop_hw;
 902	}
 903
 904	switch (id->product) {
 905	case USB_DEVICE_ID_APPLE_MAGICMOUSE:
 906		report = hid_register_report(hdev, HID_INPUT_REPORT, MOUSE_REPORT_ID, 0);
 907		break;
 908	case USB_DEVICE_ID_APPLE_MAGICMOUSE2:
 909	case USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC:
 910		report = hid_register_report(hdev, HID_INPUT_REPORT, MOUSE2_REPORT_ID, 0);
 911		break;
 912	case USB_DEVICE_ID_APPLE_MAGICTRACKPAD2:
 913	case USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC:
 914		switch (id->vendor) {
 915		case BT_VENDOR_ID_APPLE:
 916			report = hid_register_report(hdev, HID_INPUT_REPORT,
 917				TRACKPAD2_BT_REPORT_ID, 0);
 918			break;
 919		default:
 920			report = hid_register_report(hdev, HID_INPUT_REPORT,
 921				TRACKPAD2_USB_REPORT_ID, 0);
 922		}
 923		break;
 924	default: /* USB_DEVICE_ID_APPLE_MAGICTRACKPAD */
 925		report = hid_register_report(hdev, HID_INPUT_REPORT,
 926			TRACKPAD_REPORT_ID, 0);
 927		report = hid_register_report(hdev, HID_INPUT_REPORT,
 928			DOUBLE_REPORT_ID, 0);
 929	}
 930
 931	if (!report) {
 932		hid_err(hdev, "unable to register touch report\n");
 933		ret = -ENOMEM;
 934		goto err_stop_hw;
 935	}
 936	report->size = 6;
 937
 938	/*
 939	 * Some devices repond with 'invalid report id' when feature
 940	 * report switching it into multitouch mode is sent to it.
 941	 *
 942	 * This results in -EIO from the _raw low-level transport callback,
 943	 * but there seems to be no other way of switching the mode.
 944	 * Thus the super-ugly hacky success check below.
 945	 */
 946	ret = magicmouse_enable_multitouch(hdev);
 947	if (ret != -EIO && ret < 0) {
 948		hid_err(hdev, "unable to request touch data (%d)\n", ret);
 949		goto err_stop_hw;
 950	}
 951	if (ret == -EIO && (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2 ||
 952			    id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC)) {
 953		schedule_delayed_work(&msc->work, msecs_to_jiffies(500));
 954	}
 955
 956	return 0;
 957err_stop_hw:
 958	if (is_usb_magicmouse2(id->vendor, id->product) ||
 959	    is_usb_magictrackpad2(id->vendor, id->product))
 960		timer_delete_sync(&msc->battery_timer);
 961
 962	hid_hw_stop(hdev);
 963	return ret;
 964}
 965
 966static void magicmouse_remove(struct hid_device *hdev)
 967{
 968	struct magicmouse_sc *msc = hid_get_drvdata(hdev);
 969
 970	if (msc) {
 971		cancel_delayed_work_sync(&msc->work);
 972		if (is_usb_magicmouse2(hdev->vendor, hdev->product) ||
 973		    is_usb_magictrackpad2(hdev->vendor, hdev->product))
 974			timer_delete_sync(&msc->battery_timer);
 975	}
 976
 977	hid_hw_stop(hdev);
 978}
 979
 980static const __u8 *magicmouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
 981					   unsigned int *rsize)
 982{
 983	/*
 984	 * Change the usage from:
 985	 *   0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1)  0
 986	 *   0x09, 0x0b,       // Usage (Vendor Usage 0x0b)           3
 987	 * To:
 988	 *   0x05, 0x01,       // Usage Page (Generic Desktop)        0
 989	 *   0x09, 0x02,       // Usage (Mouse)                       2
 990	 */
 991	if ((is_usb_magicmouse2(hdev->vendor, hdev->product) ||
 992	     is_usb_magictrackpad2(hdev->vendor, hdev->product)) &&
 993	    *rsize >= 83 && rdesc[46] == 0x84 && rdesc[58] == 0x85) {
 994		hid_info(hdev,
 995			 "fixing up magicmouse battery report descriptor\n");
 996		*rsize = *rsize - 1;
 997		rdesc = rdesc + 1;
 998
 999		rdesc[0] = 0x05;
1000		rdesc[1] = 0x01;
1001		rdesc[2] = 0x09;
1002		rdesc[3] = 0x02;
1003	}
1004
1005	return rdesc;
1006}
1007
1008static const struct hid_device_id magic_mice[] = {
1009	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
1010		USB_DEVICE_ID_APPLE_MAGICMOUSE), .driver_data = 0 },
1011	{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
1012		USB_DEVICE_ID_APPLE_MAGICMOUSE2), .driver_data = 0 },
1013	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1014		USB_DEVICE_ID_APPLE_MAGICMOUSE2), .driver_data = 0 },
1015	{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
1016		USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC), .driver_data = 0 },
1017	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1018		USB_DEVICE_ID_APPLE_MAGICMOUSE2_USBC), .driver_data = 0 },
1019	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE,
1020		USB_DEVICE_ID_APPLE_MAGICTRACKPAD), .driver_data = 0 },
1021	{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
1022		USB_DEVICE_ID_APPLE_MAGICTRACKPAD2), .driver_data = 0 },
1023	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1024		USB_DEVICE_ID_APPLE_MAGICTRACKPAD2), .driver_data = 0 },
1025	{ HID_BLUETOOTH_DEVICE(BT_VENDOR_ID_APPLE,
1026		USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
1027	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE,
1028		USB_DEVICE_ID_APPLE_MAGICTRACKPAD2_USBC), .driver_data = 0 },
1029	{ }
1030};
1031MODULE_DEVICE_TABLE(hid, magic_mice);
1032
1033static struct hid_driver magicmouse_driver = {
1034	.name = "magicmouse",
1035	.id_table = magic_mice,
1036	.probe = magicmouse_probe,
1037	.remove = magicmouse_remove,
1038	.report_fixup = magicmouse_report_fixup,
1039	.raw_event = magicmouse_raw_event,
1040	.event = magicmouse_event,
1041	.input_mapping = magicmouse_input_mapping,
1042	.input_configured = magicmouse_input_configured,
1043};
1044module_hid_driver(magicmouse_driver);
1045
1046MODULE_DESCRIPTION("Apple \"Magic\" Wireless Mouse driver");
1047MODULE_LICENSE("GPL");
~/ Read-only file preview.