xref: /netbsd-src/sys/arch/zaurus/dev/ztp.c (revision e5fbc36ada28f9b9a5836ecffaf4a06aa1ebb687)
1 /*	$NetBSD: ztp.c,v 1.17 2023/12/20 15:34:46 thorpej Exp $	*/
2 /* $OpenBSD: zts.c,v 1.9 2005/04/24 18:55:49 uwe Exp $ */
3 
4 /*
5  * Copyright (c) 2005 Dale Rahn <drahn@openbsd.org>
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: ztp.c,v 1.17 2023/12/20 15:34:46 thorpej Exp $");
22 
23 #include "lcd.h"
24 #include "w100lcd.h"
25 
26 #include <sys/types.h>
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/device.h>
30 #include <sys/kernel.h>
31 #include <sys/callout.h>
32 
33 #include <dev/wscons/wsconsio.h>
34 #include <dev/wscons/wsmousevar.h>
35 #include <dev/wscons/wsdisplayvar.h>
36 
37 #include <dev/hpc/hpcfbio.h>		/* XXX: for tpctl */
38 #include <dev/hpc/hpctpanelvar.h>
39 
40 #include <arm/xscale/pxa2x0cpu.h>
41 #include <arm/xscale/pxa2x0reg.h>
42 #include <arm/xscale/pxa2x0var.h>
43 #include <arm/xscale/xscalereg.h>
44 #include <arm/xscale/pxa2x0_gpio.h>
45 #if NLCD > 0
46 #include <arm/xscale/pxa2x0_lcd.h>
47 #endif
48 #if NW100LCD > 0
49 #include <zaurus/dev/w100var.h>
50 #endif
51 
52 #include <zaurus/zaurus/zaurus_var.h>
53 #include <zaurus/dev/zsspvar.h>
54 #ifdef ZTP_DEBUG
55 #define	DPRINTF(s)	printf s
56 #else
57 #define	DPRINTF(s)
58 #endif
59 
60 /*
61  * ADS784x touch screen controller
62  */
63 #define ADSCTRL_PD0_SH          0       /* PD0 bit */
64 #define ADSCTRL_PD1_SH          1       /* PD1 bit */
65 #define ADSCTRL_DFR_SH          2       /* SER/DFR bit */
66 #define ADSCTRL_MOD_SH          3       /* Mode bit */
67 #define ADSCTRL_ADR_SH          4       /* Address setting */
68 #define ADSCTRL_STS_SH          7       /* Start bit */
69 
70 #define GPIO_TP_INT_C3K		11
71 #define GPIO_HSYNC_C3K		22
72 #define GPIO_TP_INT_C860	5
73 #define GPIO_HSYNC_C860		44
74 
75 #define POLL_TIMEOUT_RATE0	((hz * 150)/1000)
76 #define POLL_TIMEOUT_RATE1	(hz / 100) /* XXX every tick */
77 
78 #define CCNT_HS_400_VGA_C3K 6250	/* 15.024us */
79 #define CCNT_HS_400_VGA_C860 7013	/* 17.615us */
80 
81 /* XXX need to ask lcd drivers for the screen dimension */
82 #if NLCD > 0
83 extern const struct lcd_panel_geometry lcd_panel_geometry_c3000;
84 #endif
85 #if NW100LCD > 0
86 extern const struct w100_panel_geometry lcd_panel_geometry_c700;
87 #endif
88 
89 /* Settable via sysctl. */
90 int ztp_rawmode;
91 
92 static const struct wsmouse_calibcoords ztp_default_calib = {
93 	0, 0, 479, 639,				/* minx, miny, maxx, maxy */
94 	5,					/* samplelen */
95 	{
96 		{ 1929, 2021, 240, 320 },	/* rawx, rawy, x, y */
97 		{  545, 3464,  48,  64 },
98 		{ 3308, 3452,  48, 576 },
99 		{ 2854,  768, 432, 576 },
100 		{  542,  593, 432,  64 }
101 	}
102 };
103 
104 struct ztp_pos {
105 	int x;
106 	int y;
107 	int z;			/* touch pressure */
108 };
109 
110 struct ztp_softc {
111 	device_t sc_dev;
112 	struct callout sc_tp_poll;
113 	void *sc_gh;
114 	int sc_enabled;
115 	int sc_buttons; /* button emulation ? */
116 	device_t sc_wsmousedev;
117 	struct ztp_pos sc_oldpos;
118 	int sc_resx;
119 	int sc_resy;
120 	struct tpcalib_softc sc_tpcalib;
121 
122 	u_int sc_tp_int_pin;
123 	u_int sc_hsync_pin;
124 	u_int sc_ccnt_hs;
125 };
126 
127 static int	ztp_match(device_t, cfdata_t, void *);
128 static void	ztp_attach(device_t, device_t, void *);
129 
130 CFATTACH_DECL_NEW(ztp, sizeof(struct ztp_softc),
131 	ztp_match, ztp_attach, NULL, NULL);
132 
133 static int	ztp_finalize(device_t);
134 static int	ztp_enable(void *);
135 static void	ztp_disable(void *);
136 static bool	ztp_suspend(device_t dv, const pmf_qual_t *);
137 static bool	ztp_resume(device_t dv, const pmf_qual_t *);
138 static void	ztp_poll(void *);
139 static int	ztp_irq(void *);
140 static int	ztp_ioctl(void *, u_long, void *, int, struct lwp *);
141 
142 static const struct wsmouse_accessops ztp_accessops = {
143         ztp_enable,
144 	ztp_ioctl,
145 	ztp_disable
146 };
147 
148 static int
ztp_match(device_t parent,cfdata_t cf,void * aux)149 ztp_match(device_t parent, cfdata_t cf, void *aux)
150 {
151 	struct zssp_attach_args *aa = aux;
152 
153 	if (strcmp("ztp", aa->zaa_name))
154 		return 0;
155 	return 1;
156 }
157 
158 static void
ztp_attach(device_t parent,device_t self,void * aux)159 ztp_attach(device_t parent, device_t self, void *aux)
160 {
161 	struct ztp_softc *sc = device_private(self);
162 	struct wsmousedev_attach_args a;
163 
164 	sc->sc_dev = self;
165 
166 	aprint_normal("\n");
167 	aprint_naive("\n");
168 
169 	callout_init(&sc->sc_tp_poll, 0);
170 	callout_setfunc(&sc->sc_tp_poll, ztp_poll, sc);
171 
172 	/* defer initialization until all other devices are attached */
173 	config_finalize_register(self, ztp_finalize);
174 
175 	a.accessops = &ztp_accessops;
176 	a.accesscookie = sc;
177 
178 #if NLCD > 0 || NW100LCD > 0	/* XXX */
179 #if NLCD > 0
180 	if (ZAURUS_ISC1000 || ZAURUS_ISC3000) {
181 		sc->sc_resx = lcd_panel_geometry_c3000.panel_height;
182 		sc->sc_resy = lcd_panel_geometry_c3000.panel_width;
183 	} else
184 #endif
185 #if NW100LCD > 0
186 	if (ZAURUS_ISC860) {
187 		sc->sc_resx = lcd_panel_geometry_c700.panel_height;
188 		sc->sc_resy = lcd_panel_geometry_c700.panel_width;
189 	} else
190 #endif
191 #endif
192 	{
193 		sc->sc_resx = 480;	/* XXX */
194 		sc->sc_resy = 640;	/* XXX */
195 	}
196 
197 	if (ZAURUS_ISC1000 || ZAURUS_ISC3000) {
198 		sc->sc_tp_int_pin = GPIO_TP_INT_C3K;
199 		sc->sc_hsync_pin = GPIO_HSYNC_C3K;
200 		sc->sc_ccnt_hs = CCNT_HS_400_VGA_C3K;
201 	} else {
202 		/* C7x0/C860 */
203 		sc->sc_tp_int_pin = GPIO_TP_INT_C860;
204 		sc->sc_hsync_pin = GPIO_HSYNC_C860;
205 		sc->sc_ccnt_hs = CCNT_HS_400_VGA_C860;
206 	}
207 
208 	sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint, CFARGS_NONE);
209 
210 	/* Initialize calibration, set default parameters. */
211 	tpcalib_init(&sc->sc_tpcalib);
212 	tpcalib_ioctl(&sc->sc_tpcalib, WSMOUSEIO_SCALIBCOORDS,
213 	    __UNCONST(&ztp_default_calib), 0, 0);
214 }
215 
216 static int
ztp_finalize(device_t dv)217 ztp_finalize(device_t dv)
218 {
219 
220 	/* Initialize ADS7846 Difference Reference mode */
221 	(void)zssp_ic_send(ZSSP_IC_ADS7846,
222 	    (1<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH));
223 	delay(5000);
224 	(void)zssp_ic_send(ZSSP_IC_ADS7846,
225 	    (3<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH));
226 	delay(5000);
227 	(void)zssp_ic_send(ZSSP_IC_ADS7846,
228 	    (4<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH));
229 	delay(5000);
230 	(void)zssp_ic_send(ZSSP_IC_ADS7846,
231 	    (5<<ADSCTRL_ADR_SH) | (1<<ADSCTRL_STS_SH));
232 	delay(5000);
233 
234 	return 0;
235 }
236 
237 static int
ztp_enable(void * v)238 ztp_enable(void *v)
239 {
240 	struct ztp_softc *sc = (struct ztp_softc *)v;
241 
242 	DPRINTF(("%s: ztp_enable()\n", device_xname(sc->sc_dev)));
243 
244 	if (sc->sc_enabled) {
245 		DPRINTF(("%s: already enabled\n", device_xname(sc->sc_dev)));
246 		return EBUSY;
247 	}
248 
249 	callout_stop(&sc->sc_tp_poll);
250 
251 	if (!pmf_device_register(sc->sc_dev, ztp_suspend, ztp_resume))
252 		aprint_error_dev(sc->sc_dev,
253 		    "couldn't establish power handler\n");
254 
255 	pxa2x0_gpio_set_function(sc->sc_tp_int_pin, GPIO_IN);
256 
257 	/* XXX */
258 	if (sc->sc_gh == NULL) {
259 		sc->sc_gh = pxa2x0_gpio_intr_establish(sc->sc_tp_int_pin,
260 		    IST_EDGE_FALLING, IPL_TTY, ztp_irq, sc);
261 	} else {
262 		pxa2x0_gpio_intr_unmask(sc->sc_gh);
263 	}
264 
265 	/* enable interrupts */
266 	sc->sc_enabled = 1;
267 	sc->sc_buttons = 0;
268 
269 	return 0;
270 }
271 
272 static void
ztp_disable(void * v)273 ztp_disable(void *v)
274 {
275 	struct ztp_softc *sc = (struct ztp_softc *)v;
276 
277 	DPRINTF(("%s: ztp_disable()\n", device_xname(sc->sc_dev)));
278 
279 	callout_stop(&sc->sc_tp_poll);
280 
281 	pmf_device_deregister(sc->sc_dev);
282 
283 	if (sc->sc_gh) {
284 		pxa2x0_gpio_intr_mask(sc->sc_gh);
285 	}
286 
287 	/* disable interrupts */
288 	sc->sc_enabled = 0;
289 }
290 
291 static bool
ztp_suspend(device_t dv,const pmf_qual_t * qual)292 ztp_suspend(device_t dv, const pmf_qual_t *qual)
293 {
294 	struct ztp_softc *sc = device_private(dv);
295 
296 	DPRINTF(("%s: ztp_suspend()\n", device_xname(sc->sc_dev)));
297 
298 	sc->sc_enabled = 0;
299 	pxa2x0_gpio_intr_mask(sc->sc_gh);
300 
301 	callout_stop(&sc->sc_tp_poll);
302 
303 	/* Turn off reference voltage but leave ADC on. */
304 	(void)zssp_ic_send(ZSSP_IC_ADS7846, (1 << ADSCTRL_PD1_SH) |
305 	    (1 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH));
306 
307 	pxa2x0_gpio_set_function(sc->sc_tp_int_pin, GPIO_OUT | GPIO_SET);
308 
309 	return true;
310 }
311 
312 static bool
ztp_resume(device_t dv,const pmf_qual_t * qual)313 ztp_resume(device_t dv, const pmf_qual_t *qual)
314 {
315 	struct ztp_softc *sc = device_private(dv);
316 
317 	DPRINTF(("%s: ztp_resume()\n", device_xname(sc->sc_dev)));
318 
319 	pxa2x0_gpio_set_function(sc->sc_tp_int_pin, GPIO_IN);
320 	pxa2x0_gpio_intr_mask(sc->sc_gh);
321 
322 	/* Enable automatic low power mode. */
323 	(void)zssp_ic_send(ZSSP_IC_ADS7846,
324 	    (4 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH));
325 
326 	pxa2x0_gpio_intr_unmask(sc->sc_gh);
327 	sc->sc_enabled = 1;
328 
329 	return true;
330 }
331 
332 #define HSYNC()								\
333 do {									\
334 	while (pxa2x0_gpio_get_bit(sc->sc_hsync_pin) == 0)		\
335 		continue;						\
336 	while (pxa2x0_gpio_get_bit(sc->sc_hsync_pin) != 0)		\
337 		continue;						\
338 } while (/*CONSTCOND*/0)
339 
340 static inline uint32_t pxa2x0_ccnt_enable(uint32_t);
341 static inline uint32_t pxa2x0_read_ccnt(void);
342 static uint32_t ztp_sync_ads784x(struct ztp_softc *, int, int, uint32_t);
343 static void ztp_sync_send(struct ztp_softc *, uint32_t);
344 static int ztp_readpos(struct ztp_softc *, struct ztp_pos *);
345 
346 static inline uint32_t
pxa2x0_ccnt_enable(uint32_t reg)347 pxa2x0_ccnt_enable(uint32_t reg)
348 {
349 	uint32_t rv;
350 
351 	__asm volatile("mrc p14, 0, %0, c0, c1, 0" : "=r" (rv));
352 	__asm volatile("mcr p14, 0, %0, c0, c1, 0" : : "r" (reg));
353 
354 	return rv;
355 }
356 
357 static inline uint32_t
pxa2x0_read_ccnt(void)358 pxa2x0_read_ccnt(void)
359 {
360 	uint32_t rv;
361 
362 	__asm volatile("mrc p14, 0, %0, c1, c1, 0" : "=r" (rv));
363 
364 	return rv;
365 }
366 
367 /*
368  * Communicate synchronously with the ADS784x touch screen controller.
369  */
370 static uint32_t
ztp_sync_ads784x(struct ztp_softc * sc,int dorecv,int dosend,uint32_t cmd)371 ztp_sync_ads784x(struct ztp_softc *sc, int dorecv/* XXX */,
372     int dosend/* XXX */, uint32_t cmd)
373 {
374 	uint32_t ccen;
375 	uint32_t rv = 0;
376 
377 	/* XXX poll hsync only if LCD is enabled */
378 
379 	/* start clock counter */
380 	ccen = pxa2x0_ccnt_enable(PMNC_E);
381 
382 	HSYNC();
383 
384 	if (dorecv) {
385 		/* read SSDR and disable ADS784x */
386 		rv = zssp_ic_stop(ZSSP_IC_ADS7846);
387 	}
388 
389 	if (dosend) {
390 		ztp_sync_send(sc, cmd);
391 	}
392 
393 	/* stop clock counter */
394 	pxa2x0_ccnt_enable(ccen);
395 
396 	return rv;
397 }
398 
399 void
ztp_sync_send(struct ztp_softc * sc,uint32_t cmd)400 ztp_sync_send(struct ztp_softc *sc, uint32_t cmd)
401 {
402 	volatile uint32_t base, now;
403 	uint32_t tck;
404 
405 	/* XXX */
406 	tck = sc->sc_ccnt_hs - 151;
407 	/* XXX: for one more delay(1) */
408 	tck -= 400;
409 
410 	/* send dummy command; discard SSDR */
411 	(void)zssp_ic_send(ZSSP_IC_ADS7846, cmd);
412 
413 	/* wait for refresh */
414 	HSYNC();
415 
416 	/* wait after refresh */
417 	base = pxa2x0_read_ccnt();
418 	now = pxa2x0_read_ccnt();
419 	while ((now - base) < tck)
420 		now = pxa2x0_read_ccnt();
421 
422 	/* send the actual command; keep ADS784x enabled */
423 	zssp_ic_start(ZSSP_IC_ADS7846, cmd);
424 }
425 
426 static int
ztp_readpos(struct ztp_softc * sc,struct ztp_pos * pos)427 ztp_readpos(struct ztp_softc *sc, struct ztp_pos *pos)
428 {
429 	int cmd;
430 	int t0, t1;
431 	int down;
432 
433 	/* XXX */
434 	pxa2x0_gpio_set_function(sc->sc_hsync_pin, GPIO_IN);
435 
436 	/* check that pen is down */
437 	cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) |
438 	    (3 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH);
439 	t0 = zssp_ic_send(ZSSP_IC_ADS7846, cmd);
440 	DPRINTF(("ztp_readpos(): t0 = %d\n", t0));
441 
442 	down = (t0 >= 10);
443 	if (down == 0)
444 		goto out;
445 
446 	/* Y */
447 	cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) |
448 	    (1 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH);
449 	(void)ztp_sync_ads784x(sc, 0, 1, cmd);
450 
451 	/* Y */
452 	cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) |
453 	    (1 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH);
454 	(void)ztp_sync_ads784x(sc, 1, 1, cmd);
455 
456 	/* X */
457 	cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) |
458 	    (5 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH);
459 	pos->y = ztp_sync_ads784x(sc, 1, 1, cmd);
460 	DPRINTF(("ztp_readpos(): y = %d\n", pos->y));
461 
462 	/* T0 */
463 	cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) |
464 	    (3 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH);
465 	pos->x = ztp_sync_ads784x(sc, 1, 1, cmd);
466 	DPRINTF(("ztp_readpos(): x = %d\n", pos->x));
467 
468 	/* T1 */
469 	cmd = (1 << ADSCTRL_PD0_SH) | (1 << ADSCTRL_PD1_SH) |
470 	    (4 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH);
471 	t0 = ztp_sync_ads784x(sc, 1, 1, cmd);
472 	t1 = ztp_sync_ads784x(sc, 1, 0, cmd);
473 	DPRINTF(("ztp_readpos(): t0 = %d, t1 = %d\n", t0, t1));
474 
475 	/* check that pen is still down */
476 	/* XXX pressure sensitivity varies with X or what? */
477 	if (t0 == 0 || (pos->x * (t1 - t0) / t0) >= 15000)
478 		down = 0;
479 	pos->z = down;
480 
481 out:
482 	/* Enable automatic low power mode. */
483         cmd = (4 << ADSCTRL_ADR_SH) | (1 << ADSCTRL_STS_SH);
484 	(void)zssp_ic_send(ZSSP_IC_ADS7846, cmd);
485 
486 	return down;
487 }
488 
489 static void
ztp_poll(void * v)490 ztp_poll(void *v)
491 {
492 	int s;
493 
494 	s = spltty();
495 	(void)ztp_irq(v);
496 	splx(s);
497 }
498 
499 static int
ztp_irq(void * v)500 ztp_irq(void *v)
501 {
502 	extern int zkbd_modstate;
503 	struct ztp_softc *sc = (struct ztp_softc *)v;
504 	struct ztp_pos tp = { 0, 0, 0 };
505 	int pindown;
506 	int down;
507 	int x, y;
508 	int s;
509 
510 	if (!sc->sc_enabled)
511 		return 0;
512 
513 	s = splhigh();
514 
515 	pindown = pxa2x0_gpio_get_bit(sc->sc_tp_int_pin) ? 0 : 1;
516 	DPRINTF(("%s: pindown = %d\n", device_xname(sc->sc_dev), pindown));
517 	if (pindown) {
518 		pxa2x0_gpio_intr_mask(sc->sc_gh);
519 		callout_schedule(&sc->sc_tp_poll, POLL_TIMEOUT_RATE1);
520 	}
521 
522 	down = ztp_readpos(sc, &tp);
523 	DPRINTF(("%s: x = %d, y = %d, z = %d, down = %d\n",
524 	    device_xname(sc->sc_dev), tp.x, tp.y, tp.z, down));
525 
526 	if (!pindown) {
527 		pxa2x0_gpio_intr_unmask(sc->sc_gh);
528 		callout_schedule(&sc->sc_tp_poll, POLL_TIMEOUT_RATE0);
529 	}
530 	pxa2x0_gpio_clear_intr(sc->sc_tp_int_pin);
531 
532 	splx(s);
533 
534 	if (down) {
535 		if (!ztp_rawmode) {
536 			tpcalib_trans(&sc->sc_tpcalib, tp.x, tp.y, &x, &y);
537 			DPRINTF(("%s: x = %d, y = %d\n",
538 			    device_xname(sc->sc_dev), x, y));
539 			tp.x = x;
540 			tp.y = y;
541 		}
542 	}
543 
544 	if (zkbd_modstate != 0 && down) {
545 		if (zkbd_modstate & (1 << 1)) {
546 			/* Fn */
547 			down = 2;
548 		} else if (zkbd_modstate & (1 << 2)) {
549 			/* 'Alt' */
550 			down = 4;
551 		}
552 	}
553 	if (!down) {
554 		/* x/y values are not reliable when pen is up */
555 		tp = sc->sc_oldpos;
556 	}
557 
558 	if (down || sc->sc_buttons != down) {
559 		wsmouse_input(sc->sc_wsmousedev, down, tp.x, tp.y, 0, 0,
560 		    WSMOUSE_INPUT_ABSOLUTE_X | WSMOUSE_INPUT_ABSOLUTE_Y);
561 		sc->sc_buttons = down;
562 		sc->sc_oldpos = tp;
563 	}
564 
565 	return 1;
566 }
567 
568 static int
ztp_ioctl(void * v,u_long cmd,void * data,int flag,struct lwp * l)569 ztp_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l)
570 {
571 	struct ztp_softc *sc = (struct ztp_softc *)v;
572 	struct wsmouse_id *id;
573 
574 	switch (cmd) {
575 	case WSMOUSEIO_GTYPE:
576 		*(u_int *)data = WSMOUSE_TYPE_TPANEL;
577 		return 0;
578 
579 	case WSMOUSEIO_GETID:
580 		/*
581 		 * return unique ID string,
582 		 * "<vendor> <model> <serial number>"
583 		 */
584 		id = (struct wsmouse_id *)data;
585 		if (id->type != WSMOUSE_ID_TYPE_UIDSTR)
586 			return EINVAL;
587 		strlcpy(id->data, "Sharp SL-C3x00 SN000000", WSMOUSE_ID_MAXLEN);
588 		id->length = strlen(id->data);
589 		return 0;
590 
591 	case WSMOUSEIO_SCALIBCOORDS:
592 	case WSMOUSEIO_GCALIBCOORDS:
593 		return tpcalib_ioctl(&sc->sc_tpcalib, cmd, data, flag, l);
594 	}
595 
596 	return EPASSTHROUGH;
597 }
598