bsd_mouse.c revision f3d19aa6
1
2/*
3 * Copyright (c) 1999-2003 by The XFree86 Project, Inc.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * Except as contained in this notice, the name of the copyright holder(s)
24 * and author(s) shall not be used in advertising or otherwise to promote
25 * the sale, use or other dealings in this Software without prior written
26 * authorization from the copyright holder(s) and author(s).
27 */
28
29#include <xorg-server.h>
30
31#include <X11/X.h>
32#include "xf86.h"
33#include "xf86Priv.h"
34#include "xf86_OSlib.h"
35#include "xf86Xinput.h"
36#include "mouse.h"
37#include "xisb.h"
38#include "mipointer.h"
39#ifdef WSCONS_SUPPORT
40#include <dev/wscons/wsconsio.h>
41#endif
42#ifdef USBMOUSE_SUPPORT
43#ifdef HAS_LIB_USB_HID
44#include <usbhid.h>
45#else
46#include "usb.h"
47#endif
48
49#include <dev/usb/usb.h>
50#ifdef USB_GET_REPORT_ID
51#define USB_NEW_HID
52#endif
53
54#define HUP_GENERIC_DESKTOP     0x0001
55#define HUP_BUTTON              0x0009
56
57#define HUG_X                   0x0030
58#define HUG_Y                   0x0031
59#define HUG_Z                   0x0032
60#define HUG_WHEEL               0x0038
61
62#define HID_USAGE2(p,u) (((p) << 16) | u)
63
64/* The UMS mices have middle button as number 3 */
65#define UMS_BUT(i) ((i) == 0 ? 2 : (i) == 1 ? 0 : (i) == 2 ? 1 : (i))
66#endif /* USBMOUSE_SUPPORT */
67
68#ifdef USBMOUSE_SUPPORT
69static void usbSigioReadInput (int fd, void *closure);
70#endif
71static const char *FindDevice(InputInfoPtr, const char *, int);
72
73#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
74/* These are for FreeBSD and DragonFly */
75#define DEFAULT_MOUSE_DEV		"/dev/mouse"
76#define DEFAULT_SYSMOUSE_DEV		"/dev/sysmouse"
77#define DEFAULT_PS2_DEV			"/dev/psm0"
78
79static const char *mouseDevs[] = {
80	DEFAULT_MOUSE_DEV,
81	DEFAULT_SYSMOUSE_DEV,
82	DEFAULT_PS2_DEV,
83	NULL
84};
85#elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
86/* Only wsmouse mices are autoconfigured for now on OpenBSD */
87#define DEFAULT_WSMOUSE_DEV		"/dev/wsmouse"
88#define DEFAULT_WSMOUSE0_DEV		"/dev/wsmouse0"
89
90static const char *mouseDevs[] = {
91	DEFAULT_WSMOUSE_DEV,
92	DEFAULT_WSMOUSE0_DEV,
93	NULL
94};
95#endif
96
97static int
98SupportedInterfaces(void)
99{
100#if defined(__NetBSD__)
101    return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC;
102#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
103    return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_AUTO | MSE_MISC;
104#else
105    return MSE_SERIAL | MSE_BUS | MSE_PS2 | MSE_XPS2 | MSE_AUTO | MSE_MISC;
106#endif
107}
108
109/* Names of protocols that are handled internally here. */
110static const char *internalNames[] = {
111#if defined(WSCONS_SUPPORT)
112	"WSMouse",
113#endif
114#if defined(USBMOUSE_SUPPORT)
115	"usb",
116#endif
117	NULL
118};
119
120/*
121 * Names of MSC_MISC protocols that the OS supports.  These are decoded by
122 * main "mouse" driver.
123 */
124static const char *miscNames[] = {
125#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
126	"SysMouse",
127#endif
128	NULL
129};
130
131static const char **
132BuiltinNames(void)
133{
134    return internalNames;
135}
136
137static Bool
138CheckProtocol(const char *protocol)
139{
140    int i;
141
142    for (i = 0; internalNames[i]; i++)
143	if (xf86NameCmp(protocol, internalNames[i]) == 0)
144	    return TRUE;
145    for (i = 0; miscNames[i]; i++)
146	if (xf86NameCmp(protocol, miscNames[i]) == 0)
147	    return TRUE;
148    return FALSE;
149}
150
151static const char *
152DefaultProtocol(void)
153{
154#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
155    return "Auto";
156#elif (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
157    return "WSMouse";
158#else
159    return NULL;
160#endif
161}
162
163#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE)
164static struct {
165	int dproto;
166	const char *name;
167} devproto[] = {
168	{ MOUSE_PROTO_MS,		"Microsoft" },
169	{ MOUSE_PROTO_MSC,		"MouseSystems" },
170	{ MOUSE_PROTO_LOGI,		"Logitech" },
171	{ MOUSE_PROTO_MM,		"MMSeries" },
172	{ MOUSE_PROTO_LOGIMOUSEMAN,	"MouseMan" },
173	{ MOUSE_PROTO_BUS,		"BusMouse" },
174	{ MOUSE_PROTO_INPORT,		"BusMouse" },
175	{ MOUSE_PROTO_PS2,		"PS/2" },
176	{ MOUSE_PROTO_HITTAB,		"MMHitTab" },
177	{ MOUSE_PROTO_GLIDEPOINT,	"GlidePoint" },
178	{ MOUSE_PROTO_INTELLI,		"Intellimouse" },
179	{ MOUSE_PROTO_THINK,		"ThinkingMouse" },
180	{ MOUSE_PROTO_SYSMOUSE,		"SysMouse" }
181};
182
183static const char *
184SetupAuto(InputInfoPtr pInfo, int *protoPara)
185{
186    int i;
187    mousehw_t hw;
188    mousemode_t mode;
189
190    if (pInfo->fd == -1)
191	return NULL;
192
193    /* set the driver operation level, if applicable */
194    i = 1;
195    ioctl(pInfo->fd, MOUSE_SETLEVEL, &i);
196
197    /* interrogate the driver and get some intelligence on the device. */
198    hw.iftype = MOUSE_IF_UNKNOWN;
199    hw.model = MOUSE_MODEL_GENERIC;
200    ioctl(pInfo->fd, MOUSE_GETHWINFO, &hw);
201    xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: hw.iftype is %d, hw.model is %d\n",
202		pInfo->name, hw.iftype, hw.model);
203    if (ioctl(pInfo->fd, MOUSE_GETMODE, &mode) == 0) {
204	for (i = 0; i < sizeof(devproto)/sizeof(devproto[0]); ++i) {
205	    if (mode.protocol == devproto[i].dproto) {
206		/* override some parameters */
207		if (protoPara) {
208		    protoPara[4] = mode.packetsize;
209		    protoPara[0] = mode.syncmask[0];
210		    protoPara[1] = mode.syncmask[1];
211		}
212		xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n",
213			    pInfo->name, devproto[i].name);
214		return devproto[i].name;
215	    }
216	}
217    }
218    return NULL;
219}
220
221static void
222SetSysMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res)
223{
224    mousemode_t mode;
225    MouseDevPtr pMse;
226
227    pMse = pInfo->private;
228
229    mode.rate = rate > 0 ? rate : -1;
230    mode.resolution = res > 0 ? res : -1;
231    mode.accelfactor = -1;
232#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
233    if (pMse->autoProbe ||
234	(protocol && xf86NameCmp(protocol, "SysMouse") == 0)) {
235	/*
236	 * As the FreeBSD sysmouse driver defaults to protocol level 0
237	 * everytime it is opened we enforce protocol level 1 again at
238	 * this point.
239	 */
240	mode.level = 1;
241    } else
242	mode.level = -1;
243#else
244    mode.level = -1;
245#endif
246    ioctl(pInfo->fd, MOUSE_SETMODE, &mode);
247}
248#endif
249
250#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
251
252#define MOUSED_PID_FILE "/var/run/moused.pid"
253
254/*
255 * Try to check if moused is running.  DEFAULT_SYSMOUSE_DEV is useless without
256 * it.  There doesn't seem to be a better way of checking.
257 */
258static Bool
259MousedRunning(void)
260{
261    FILE *f = NULL;
262    unsigned int pid;
263
264    if ((f = fopen(MOUSED_PID_FILE, "r")) != NULL) {
265	if (fscanf(f, "%u", &pid) == 1 && pid > 0) {
266	    if (kill(pid, 0) == 0) {
267		fclose(f);
268		return TRUE;
269	    }
270	}
271	fclose(f);
272    }
273    return FALSE;
274}
275
276static const char *
277FindDevice(InputInfoPtr pInfo, const char *protocol, int flags)
278{
279    int fd = -1;
280    const char **pdev, *dev = NULL;
281    Bool devMouse = FALSE;
282    struct stat devMouseStat;
283    struct stat sb;
284
285    for (pdev = mouseDevs; *pdev; pdev++) {
286	SYSCALL (fd = open(*pdev, O_RDWR | O_NONBLOCK));
287	if (fd == -1) {
288#ifdef DEBUG
289	    ErrorF("Cannot open %s (%s)\n", *pdev, strerror(errno));
290#endif
291	} else {
292	    /*
293	     * /dev/mouse is held until checks for matches with other devices
294	     * are done.  This is so that when it points to /dev/sysmouse,
295	     * the test for whether /dev/sysmouse is usable can be made.
296	     */
297	    if (!strcmp(*pdev, DEFAULT_MOUSE_DEV)) {
298		if (fstat(fd, &devMouseStat) == 0)
299		    devMouse = TRUE;
300		close(fd);
301		continue;
302	    } else if (!strcmp(*pdev, DEFAULT_SYSMOUSE_DEV)) {
303		/* Check if /dev/mouse is the same as /dev/sysmouse. */
304		if (devMouse && fstat(fd, &sb) == 0 &&
305		    devMouseStat.st_dev == sb.st_dev &&
306		    devMouseStat.st_ino == sb.st_ino) {
307		    /* If the same, use /dev/sysmouse. */
308		    devMouse = FALSE;
309		}
310		close(fd);
311		if (MousedRunning())
312		    break;
313		else {
314#ifdef DEBUG
315	    	    ErrorF("moused isn't running\n");
316#endif
317		}
318	    } else {
319		close(fd);
320		break;
321	    }
322	}
323    }
324
325    if (*pdev)
326	dev = *pdev;
327    else if (devMouse)
328	dev = DEFAULT_MOUSE_DEV;
329
330    if (dev) {
331	/* Set the Device option. */
332	pInfo->options =
333	    xf86AddNewOption(pInfo->options, "Device", dev);
334	xf86Msg(X_INFO, "%s: Setting Device option to \"%s\"\n",
335		pInfo->name, dev);
336    }
337
338    return *pdev;
339}
340#endif
341
342#if (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
343
344/* Only support wsmouse configuration for now */
345static const char *
346SetupAuto(InputInfoPtr pInfo, int *protoPara)
347{
348
349    xf86MsgVerb(X_INFO, 3, "%s: SetupAuto: protocol is %s\n",
350		pInfo->name, "wsmouse");
351    return "wsmouse";
352}
353
354static void
355SetMouseRes(InputInfoPtr pInfo, const char *protocol, int rate, int res)
356{
357
358    xf86MsgVerb(X_INFO, 3, "%s: SetMouseRes: protocol %s rate %d res %d\n",
359	    pInfo->name, protocol, rate, res);
360}
361
362static const char *
363FindDevice(InputInfoPtr pInfo, const char *protocol, int flags)
364{
365    int fd = -1;
366    const char **pdev;
367
368    for (pdev = mouseDevs; *pdev; pdev++) {
369	SYSCALL(fd = open(*pdev, O_RDWR | O_NONBLOCK));
370	if (fd != -1) {
371	    /* Set the Device option. */
372	    pInfo->options =
373		xf86AddNewOption(pInfo->options,
374				 "Device", *pdev);
375	    xf86Msg(X_INFO, "%s: found Device \"%s\"\n",
376		    pInfo->name, *pdev);
377	    close(fd);
378	    break;
379	}
380    }
381    return *pdev;
382}
383#endif /* __OpenBSD__ || __NetBSD__ && WSCONS_SUPPORT */
384
385#ifdef WSCONS_SUPPORT
386#define NUMEVENTS 64
387
388static void
389wsconsReadInput(InputInfoPtr pInfo)
390{
391    MouseDevPtr pMse;
392    static struct wscons_event eventList[NUMEVENTS];
393    int n, c;
394    struct wscons_event *event = eventList;
395    unsigned char *pBuf;
396
397    pMse = pInfo->private;
398
399    XisbBlockDuration(pMse->buffer, -1);
400    pBuf = (unsigned char *)eventList;
401    n = 0;
402    while (n < sizeof(eventList) && (c = XisbRead(pMse->buffer)) >= 0) {
403	pBuf[n++] = (unsigned char)c;
404    }
405
406    if (n == 0)
407	return;
408
409    n /= sizeof(struct wscons_event);
410    while( n-- ) {
411	int buttons = pMse->lastButtons;
412	int dx = 0, dy = 0, dz = 0, dw = 0, x, y;
413	switch (event->type) {
414	case WSCONS_EVENT_MOUSE_UP:
415#define BUTBIT (1 << (event->value <= 2 ? 2 - event->value : event->value))
416	    buttons &= ~BUTBIT;
417	    break;
418	case WSCONS_EVENT_MOUSE_DOWN:
419	    buttons |= BUTBIT;
420	    break;
421	case WSCONS_EVENT_MOUSE_DELTA_X:
422	    dx = event->value;
423	    break;
424	case WSCONS_EVENT_MOUSE_DELTA_Y:
425	    dy = -event->value;
426	    break;
427#ifdef WSCONS_EVENT_MOUSE_DELTA_Z
428	case WSCONS_EVENT_MOUSE_DELTA_Z:
429	    dz = event->value;
430	    break;
431#endif
432#ifdef WSCONS_EVENT_MOUSE_DELTA_W
433	case WSCONS_EVENT_MOUSE_DELTA_W:
434	    dw = event->value;
435	    break;
436#endif
437	case WSCONS_EVENT_MOUSE_ABSOLUTE_X:
438	    miPointerGetPosition (pInfo->dev, &x, &y);
439	    x = event->value;
440	    miPointerSetPosition (pInfo->dev, &x, &y);
441	    xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, x, y);
442	    ++event;
443	    continue;
444	case WSCONS_EVENT_MOUSE_ABSOLUTE_Y:
445	    miPointerGetPosition (pInfo->dev, &x, &y);
446	    y = event->value;
447	    miPointerSetPosition (pInfo->dev, &x, &y);
448	    xf86PostMotionEvent(pInfo->dev, TRUE, 0, 2, x, y);
449	    ++event;
450	    continue;
451#ifdef WSCONS_EVENT_MOUSE_ABSOLUTE_Z
452	case WSCONS_EVENT_MOUSE_ABSOLUTE_Z:
453	    ++event;
454	    continue;
455#endif
456#ifdef WSCONS_EVENT_MOUSE_ABSOLUTE_W
457	case WSCONS_EVENT_MOUSE_ABSOLUTE_W:
458	    ++event;
459	    continue;
460#endif
461	default:
462	    xf86Msg(X_WARNING, "%s: bad wsmouse event type=%d\n", pInfo->name,
463		    event->type);
464	    ++event;
465	    continue;
466	}
467
468	pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
469	++event;
470    }
471    return;
472}
473
474
475/* This function is called when the protocol is "wsmouse". */
476static Bool
477wsconsPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
478{
479    MouseDevPtr pMse = pInfo->private;
480
481    /* Setup the local input proc. */
482    pInfo->read_input = wsconsReadInput;
483    pMse->xisbscale = sizeof(struct wscons_event);
484
485#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
486    pInfo->flags |= XI86_CONFIGURED;
487#endif
488    return TRUE;
489}
490#endif
491
492#if defined(USBMOUSE_SUPPORT)
493
494typedef struct _UsbMseRec {
495    int packetSize;
496    int iid;
497    hid_item_t loc_x;		/* x locator item */
498    hid_item_t loc_y;		/* y locator item */
499    hid_item_t loc_z;		/* z (wheel) locator item */
500    hid_item_t loc_w;		/* z (wheel) locator item */
501    hid_item_t loc_btn[MSE_MAXBUTTONS]; /* buttons locator items */
502   unsigned char *buffer;
503} UsbMseRec, *UsbMsePtr;
504
505static int
506usbMouseProc(DeviceIntPtr pPointer, int what)
507{
508    InputInfoPtr pInfo;
509    MouseDevPtr pMse;
510    UsbMsePtr pUsbMse;
511    unsigned char map[MSE_MAXBUTTONS + 1];
512    int nbuttons;
513
514    pInfo = pPointer->public.devicePrivate;
515    pMse = pInfo->private;
516    pMse->device = pPointer;
517    pUsbMse = pMse->mousePriv;
518
519    switch (what) {
520    case DEVICE_INIT:
521	pPointer->public.on = FALSE;
522
523	for (nbuttons = 0; nbuttons < MSE_MAXBUTTONS; ++nbuttons)
524	    map[nbuttons + 1] = nbuttons + 1;
525
526	InitPointerDeviceStruct((DevicePtr)pPointer,
527				map,
528				min(pMse->buttons, MSE_MAXBUTTONS),
529				miPointerGetMotionEvents,
530				pMse->Ctrl,
531				miPointerGetMotionBufferSize());
532
533	/* X valuator */
534	xf86InitValuatorAxisStruct(pPointer, 0, 0, -1, 1, 0, 1);
535	xf86InitValuatorDefaults(pPointer, 0);
536	/* Y valuator */
537	xf86InitValuatorAxisStruct(pPointer, 1, 0, -1, 1, 0, 1);
538	xf86InitValuatorDefaults(pPointer, 1);
539	xf86MotionHistoryAllocate(pInfo);
540	break;
541
542    case DEVICE_ON:
543	pInfo->fd = xf86OpenSerial(pInfo->options);
544	if (pInfo->fd == -1)
545	    xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
546	else {
547	    pMse->buffer = XisbNew(pInfo->fd, pUsbMse->packetSize);
548	    if (!pMse->buffer) {
549		free(pMse);
550		xf86CloseSerial(pInfo->fd);
551		pInfo->fd = -1;
552	    } else {
553		xf86FlushInput(pInfo->fd);
554		if (!xf86InstallSIGIOHandler (pInfo->fd, usbSigioReadInput,
555					      pInfo))
556		    AddEnabledDevice(pInfo->fd);
557	    }
558	}
559	pMse->lastButtons = 0;
560	pMse->lastMappedButtons = 0;
561	pMse->emulateState = 0;
562	pPointer->public.on = TRUE;
563	break;
564
565    case DEVICE_OFF:
566    case DEVICE_CLOSE:
567	if (pInfo->fd != -1) {
568	    RemoveEnabledDevice(pInfo->fd);
569	    if (pUsbMse->packetSize > 8 && pUsbMse->buffer) {
570		free(pUsbMse->buffer);
571	    }
572	    if (pMse->buffer) {
573		XisbFree(pMse->buffer);
574		pMse->buffer = NULL;
575	    }
576	    xf86CloseSerial(pInfo->fd);
577	    pInfo->fd = -1;
578	}
579	pPointer->public.on = FALSE;
580	usleep(300000);
581	break;
582    }
583    return Success;
584}
585
586static void
587usbReadInput(InputInfoPtr pInfo)
588{
589    MouseDevPtr pMse;
590    UsbMsePtr pUsbMse;
591    int buttons = pMse->lastButtons;
592    int dx = 0, dy = 0, dz = 0, dw = 0;
593    int n, c;
594    unsigned char *pBuf;
595
596    pMse = pInfo->private;
597    pUsbMse = pMse->mousePriv;
598
599    XisbBlockDuration(pMse->buffer, -1);
600    pBuf = pUsbMse->buffer;
601    n = 0;
602    while ((c = XisbRead(pMse->buffer)) >= 0 && n < pUsbMse->packetSize) {
603	pBuf[n++] = (unsigned char)c;
604    }
605    if (n == 0)
606	return;
607    if (n != pUsbMse->packetSize) {
608	xf86Msg(X_WARNING, "%s: incomplete packet, size %d\n", pInfo->name,
609		n);
610    }
611    /* discard packets with an id that don't match the mouse */
612    /* XXX this is probably not the right thing */
613    if (pUsbMse->iid != 0) {
614	if (*pBuf++ != pUsbMse->iid)
615	    return;
616    }
617    dx = hid_get_data(pBuf, &pUsbMse->loc_x);
618    dy = hid_get_data(pBuf, &pUsbMse->loc_y);
619    dz = hid_get_data(pBuf, &pUsbMse->loc_z);
620    dw = hid_get_data(pBuf, &pUsbMse->loc_w);
621
622    buttons = 0;
623    for (n = 0; n < pMse->buttons; n++) {
624	if (hid_get_data(pBuf, &pUsbMse->loc_btn[n]))
625	    buttons |= (1 << UMS_BUT(n));
626    }
627    pMse->PostEvent(pInfo, buttons, dx, dy, dz, dw);
628    return;
629}
630
631static void
632usbSigioReadInput (int fd, void *closure)
633{
634    usbReadInput ((InputInfoPtr) closure);
635}
636
637/* This function is called when the protocol is "usb". */
638static Bool
639usbPreInit(InputInfoPtr pInfo, const char *protocol, int flags)
640{
641    MouseDevPtr pMse = pInfo->private;
642    UsbMsePtr pUsbMse;
643    report_desc_t reportDesc;
644    int i;
645
646    pUsbMse = malloc(sizeof(UsbMseRec));
647    if (pUsbMse == NULL) {
648	xf86Msg(X_ERROR, "%s: cannot allocate UsbMouseRec\n", pInfo->name);
649	free(pMse);
650	return FALSE;
651    }
652
653    pMse->protocol = protocol;
654    xf86Msg(X_CONFIG, "%s: Protocol: %s\n", pInfo->name, protocol);
655
656    /* Collect the options, and process the common options. */
657    COLLECT_INPUT_OPTIONS(pInfo, NULL);
658    xf86ProcessCommonOptions(pInfo, pInfo->options);
659
660    /* Check if the device can be opened. */
661    pInfo->fd = xf86OpenSerial(pInfo->options);
662    if (pInfo->fd == -1) {
663	if (xf86GetAllowMouseOpenFail())
664	    xf86Msg(X_WARNING, "%s: cannot open input device\n", pInfo->name);
665	else {
666	    xf86Msg(X_ERROR, "%s: cannot open input device\n", pInfo->name);
667	    free(pUsbMse);
668	    free(pMse);
669	    return FALSE;
670	}
671    }
672    /* Get USB informations */
673    reportDesc = hid_get_report_desc(pInfo->fd);
674    /* Get packet size & iid */
675#ifdef USB_NEW_HID
676    if (ioctl(pInfo->fd, USB_GET_REPORT_ID, &pUsbMse->iid) == -1) {
677	    xf86Msg(X_ERROR, "Error ioctl USB_GET_REPORT_ID on %s : %s\n",
678		    pInfo->name, strerror(errno));
679	    return FALSE;
680    }
681    pUsbMse->packetSize = hid_report_size(reportDesc, hid_input,
682					      pUsbMse->iid);
683#else
684    pUsbMse->packetSize = hid_report_size(reportDesc, hid_input,
685					      &pUsbMse->iid);
686#endif
687    /* Allocate buffer */
688    if (pUsbMse->packetSize <= 8) {
689	pUsbMse->buffer = pMse->protoBuf;
690    } else {
691	pUsbMse->buffer = malloc(pUsbMse->packetSize);
692    }
693    if (pUsbMse->buffer == NULL) {
694	xf86Msg(X_ERROR, "%s: cannot allocate buffer\n", pInfo->name);
695	free(pUsbMse);
696	free(pMse);
697	xf86CloseSerial(pInfo->fd);
698	return FALSE;
699    }
700#ifdef USB_NEW_HID
701    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
702		   hid_input, &pUsbMse->loc_x, pUsbMse->iid) < 0) {
703	xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name);
704    }
705    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
706		   hid_input, &pUsbMse->loc_y, pUsbMse->iid) < 0) {
707	xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name);
708    }
709    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
710		   hid_input, &pUsbMse->loc_z, pUsbMse->iid) < 0) {
711    }
712#else
713    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X),
714		   hid_input, &pUsbMse->loc_x) < 0) {
715	xf86Msg(X_WARNING, "%s: no x locator\n", pInfo->name);
716    }
717    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y),
718		   hid_input, &pUsbMse->loc_y) < 0) {
719	xf86Msg(X_WARNING, "%s: no y locator\n", pInfo->name);
720    }
721    if (hid_locate(reportDesc, HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_WHEEL),
722		   hid_input, &pUsbMse->loc_z) < 0) {
723    }
724#endif
725    /* Probe for number of buttons */
726    for (i = 1; i <= MSE_MAXBUTTONS; i++) {
727	if (!hid_locate(reportDesc, HID_USAGE2(HUP_BUTTON, i),
728			hid_input, &pUsbMse->loc_btn[i-1]
729#ifdef USB_NEW_HID
730			, pUsbMse->iid
731#endif
732			))
733	    break;
734    }
735    pMse->buttons = i-1;
736
737    xf86CloseSerial(pInfo->fd);
738    pInfo->fd = -1;
739
740    /* Private structure */
741    pMse->mousePriv = pUsbMse;
742
743    /* Process common mouse options (like Emulate3Buttons, etc). */
744    pMse->CommonOptions(pInfo);
745
746    /* Setup the local procs. */
747    pInfo->device_control = usbMouseProc;
748    pInfo->read_input = usbReadInput;
749
750#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 12
751    pInfo->flags |= XI86_CONFIGURED;
752#endif
753    return TRUE;
754}
755#endif /* USBMOUSE */
756
757static Bool
758bsdMousePreInit(InputInfoPtr pInfo, const char *protocol, int flags)
759{
760    /* The protocol is guaranteed to be one of the internalNames[] */
761#ifdef WSCONS_SUPPORT
762    if (xf86NameCmp(protocol, "WSMouse") == 0) {
763	return wsconsPreInit(pInfo, protocol, flags);
764    }
765#endif
766#ifdef USBMOUSE_SUPPORT
767    if (xf86NameCmp(protocol, "usb") == 0) {
768	return usbPreInit(pInfo, protocol, flags);
769    }
770#endif
771    return TRUE;
772}
773
774OSMouseInfoPtr
775OSMouseInit(int flags)
776{
777    OSMouseInfoPtr p;
778
779    p = calloc(sizeof(OSMouseInfoRec), 1);
780    if (!p)
781	return NULL;
782    p->SupportedInterfaces = SupportedInterfaces;
783    p->BuiltinNames = BuiltinNames;
784    p->DefaultProtocol = DefaultProtocol;
785    p->CheckProtocol = CheckProtocol;
786#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)) && defined(MOUSE_PROTO_SYSMOUSE)
787    p->SetupAuto = SetupAuto;
788    p->SetPS2Res = SetSysMouseRes;
789    p->SetBMRes = SetSysMouseRes;
790    p->SetMiscRes = SetSysMouseRes;
791#endif
792#if (defined(__OpenBSD__) || defined(__NetBSD__)) && defined(WSCONS_SUPPORT)
793    p->SetupAuto = SetupAuto;
794    p->SetMiscRes = SetMouseRes;
795#endif
796#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__NetBSD__)
797    p->FindDevice = FindDevice;
798#endif
799    p->PreInit = bsdMousePreInit;
800    return p;
801}
802