LCOV - code coverage report
Current view: top level - dev/hid - hidmt.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 218 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: hidmt.c,v 1.9 2018/08/25 20:31:31 jcs Exp $ */
       2             : /*
       3             :  * HID multitouch driver for devices conforming to Windows Precision Touchpad
       4             :  * standard
       5             :  *
       6             :  * https://msdn.microsoft.com/en-us/library/windows/hardware/dn467314%28v=vs.85%29.aspx
       7             :  * https://docs.microsoft.com/en-us/windows-hardware/design/component-guidelines/touchscreen-packet-reporting-modes
       8             :  *
       9             :  * Copyright (c) 2016 joshua stein <jcs@openbsd.org>
      10             :  *
      11             :  * Permission to use, copy, modify, and distribute this software for any
      12             :  * purpose with or without fee is hereby granted, provided that the above
      13             :  * copyright notice and this permission notice appear in all copies.
      14             :  *
      15             :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      16             :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      17             :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      18             :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      19             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      20             :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      21             :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      22             :  */
      23             : 
      24             : #include <sys/param.h>
      25             : #include <sys/systm.h>
      26             : #include <sys/kernel.h>
      27             : #include <sys/device.h>
      28             : #include <sys/ioctl.h>
      29             : #include <sys/malloc.h>
      30             : 
      31             : #include <dev/wscons/wsconsio.h>
      32             : #include <dev/wscons/wsmousevar.h>
      33             : 
      34             : #include <dev/hid/hid.h>
      35             : #include <dev/hid/hidmtvar.h>
      36             : 
      37             : /* #define HIDMT_DEBUG */
      38             : 
      39             : #ifdef HIDMT_DEBUG
      40             : #define DPRINTF(x) printf x
      41             : #else
      42             : #define DPRINTF(x)
      43             : #endif
      44             : 
      45             : #define HID_UNIT_CM     0x11
      46             : #define HID_UNIT_INCH   0x13
      47             : 
      48             : /*
      49             :  * Calculate the horizontal or vertical resolution, in device units per
      50             :  * millimeter.
      51             :  *
      52             :  * With the length unit specified by the descriptor (centimeter or inch),
      53             :  * the result is:
      54             :  *     (logical_maximum - logical_minimum) / ((physical_maximum -
      55             :  *         physical_minimum) * 10^unit_exponent)
      56             :  *
      57             :  * The descriptors should encode the unit exponent as a signed half-byte.
      58             :  * However, this function accepts the values from -8 to -1 in both the
      59             :  * 4-bit format and the usual encoding.  Other values beyond the 4-bit
      60             :  * range are treated as undefined.  Possibly a misinterpretation of
      61             :  * section 6.2.2.7 of the HID specification (v1.11) has been turned into
      62             :  * a standard here, see (from www.usb.org)
      63             :  *     HUTRR39: "HID Sensor Usage Tables", sect. 3.9, 3.10, 4.2.1
      64             :  * for an official exegesis and
      65             :  *     https://patchwork.kernel.org/patch/3033191
      66             :  * for details and a different view.
      67             :  */
      68             : int
      69           0 : hidmt_get_resolution(struct hid_item *h)
      70             : {
      71             :         int log_extent, phy_extent, exponent;
      72             : 
      73           0 :         if (h->unit != HID_UNIT_CM && h->unit != HID_UNIT_INCH)
      74           0 :                 return (0);
      75             : 
      76           0 :         log_extent = h->logical_maximum - h->logical_minimum;
      77           0 :         phy_extent = h->physical_maximum - h->physical_minimum;
      78           0 :         if (log_extent <= 0 || phy_extent <= 0)
      79           0 :                 return (0);
      80             : 
      81           0 :         exponent = h->unit_exponent;
      82           0 :         if (exponent < -8 || exponent > 15)               /* See above. */
      83           0 :                 return (0);
      84           0 :         if (exponent > 7)
      85           0 :                 exponent -= 16;
      86             : 
      87           0 :         for (; exponent < 0 && log_extent <= INT_MAX / 10; exponent++)
      88           0 :                 log_extent *= 10;
      89           0 :         for (; exponent > 0 && phy_extent <= INT_MAX / 10; exponent--)
      90           0 :                 phy_extent *= 10;
      91           0 :         if (exponent != 0)
      92           0 :                 return (0);
      93             : 
      94           0 :         if (h->unit == HID_UNIT_INCH) {                      /* Map inches to mm. */
      95           0 :                 if ((phy_extent > INT_MAX / 127)
      96           0 :                     || (log_extent > INT_MAX / 5))
      97           0 :                         return (0);
      98           0 :                 log_extent *= 5;
      99           0 :                 phy_extent *= 127;
     100           0 :         } else {                                        /* Map cm to mm. */
     101           0 :                 if (phy_extent > INT_MAX / 10)
     102           0 :                         return (0);
     103           0 :                 phy_extent *= 10;
     104             :         }
     105             : 
     106           0 :         return (log_extent / phy_extent);
     107           0 : }
     108             : 
     109             : int
     110           0 : hidmt_setup(struct device *self, struct hidmt *mt, void *desc, int dlen)
     111             : {
     112           0 :         struct hid_location cap;
     113             :         int32_t d;
     114             :         uint8_t *rep;
     115             :         int capsize;
     116             : 
     117             :         struct hid_data *hd;
     118           0 :         struct hid_item h;
     119             : 
     120           0 :         mt->sc_device = self;
     121           0 :         mt->sc_rep_input_size = hid_report_size(desc, dlen, hid_input,
     122           0 :             mt->sc_rep_input);
     123             : 
     124           0 :         mt->sc_minx = mt->sc_miny = mt->sc_maxx = mt->sc_maxy = 0;
     125             : 
     126           0 :         capsize = hid_report_size(desc, dlen, hid_feature, mt->sc_rep_cap);
     127           0 :         rep = malloc(capsize, M_DEVBUF, M_NOWAIT | M_ZERO);
     128             : 
     129           0 :         if (mt->hidev_report_type_conv == NULL)
     130           0 :                 panic("no report type conversion function");
     131             : 
     132           0 :         if (mt->hidev_get_report(mt->sc_device,
     133           0 :             mt->hidev_report_type_conv(hid_feature), mt->sc_rep_cap,
     134             :             rep, capsize)) {
     135           0 :                 printf("\n%s: failed getting capability report\n",
     136           0 :                     self->dv_xname);
     137           0 :                 return 1;
     138             :         }
     139             : 
     140             :         /* find maximum number of contacts being reported per input report */
     141           0 :         if (!hid_locate(desc, dlen, HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACT_MAX),
     142           0 :             mt->sc_rep_cap, hid_feature, &cap, NULL)) {
     143           0 :                 printf("\n%s: can't find maximum contacts\n", self->dv_xname);
     144           0 :                 return 1;
     145             :         }
     146             : 
     147           0 :         d = hid_get_udata(rep, capsize, &cap);
     148           0 :         if (d > HIDMT_MAX_CONTACTS) {
     149           0 :                 printf("\n%s: contacts %d > max %d\n", self->dv_xname, d,
     150             :                     HIDMT_MAX_CONTACTS);
     151           0 :                 return 1;
     152             :         }
     153             :         else
     154           0 :                 mt->sc_num_contacts = d;
     155             : 
     156             :         /* find whether this is a clickpad or not */
     157           0 :         if (!hid_locate(desc, dlen, HID_USAGE2(HUP_DIGITIZERS, HUD_BUTTON_TYPE),
     158           0 :             mt->sc_rep_cap, hid_feature, &cap, NULL)) {
     159           0 :                 printf("\n%s: can't find button type\n", self->dv_xname);
     160           0 :                 return 1;
     161             :         }
     162             : 
     163           0 :         d = hid_get_udata(rep, capsize, &cap);
     164           0 :         mt->sc_clickpad = (d == 0);
     165             : 
     166             :         /*
     167             :          * Walk HID descriptor and store usages we care about to know what to
     168             :          * pluck out of input reports.
     169             :          */
     170             : 
     171           0 :         SIMPLEQ_INIT(&mt->sc_inputs);
     172             : 
     173           0 :         hd = hid_start_parse(desc, dlen, hid_input);
     174           0 :         while (hid_get_item(hd, &h)) {
     175             :                 struct hidmt_data *input;
     176             : 
     177           0 :                 if (h.report_ID != mt->sc_rep_input)
     178           0 :                         continue;
     179             : 
     180           0 :                 switch (h.usage) {
     181             :                 /* contact level usages */
     182             :                 case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X):
     183           0 :                         if (h.logical_maximum - h.logical_minimum) {
     184           0 :                                 mt->sc_minx = h.logical_minimum;
     185           0 :                                 mt->sc_maxx = h.logical_maximum;
     186           0 :                                 mt->sc_resx = hidmt_get_resolution(&h);
     187           0 :                         }
     188             :                         break;
     189             :                 case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y):
     190           0 :                         if (h.logical_maximum - h.logical_minimum) {
     191           0 :                                 mt->sc_miny = h.logical_minimum;
     192           0 :                                 mt->sc_maxy = h.logical_maximum;
     193           0 :                                 mt->sc_resy = hidmt_get_resolution(&h);
     194           0 :                         }
     195             :                         break;
     196             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_SWITCH):
     197             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_CONFIDENCE):
     198             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_WIDTH):
     199             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_HEIGHT):
     200             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACTID):
     201             : 
     202             :                 /* report level usages */
     203             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACTCOUNT):
     204             :                 case HID_USAGE2(HUP_BUTTON, 0x01):
     205             :                         break;
     206             :                 default:
     207           0 :                         continue;
     208             :                 }
     209             : 
     210           0 :                 input = malloc(sizeof(*input), M_DEVBUF, M_NOWAIT | M_ZERO);
     211           0 :                 memcpy(&input->loc, &h.loc, sizeof(struct hid_location));
     212           0 :                 input->usage = h.usage;
     213             : 
     214           0 :                 SIMPLEQ_INSERT_TAIL(&mt->sc_inputs, input, entry);
     215           0 :         }
     216           0 :         hid_end_parse(hd);
     217             : 
     218           0 :         if (mt->sc_maxx <= 0 || mt->sc_maxy <= 0) {
     219           0 :                 printf("\n%s: invalid max X/Y %d/%d\n", self->dv_xname,
     220           0 :                     mt->sc_maxx, mt->sc_maxy);
     221           0 :                 return 1;
     222             :         }
     223             : 
     224           0 :         if (hidmt_set_input_mode(mt, HIDMT_INPUT_MODE_MT_TOUCHPAD)) {
     225           0 :                 printf("\n%s: switch to multitouch mode failed\n",
     226           0 :                     self->dv_xname);
     227           0 :                 return 1;
     228             :         }
     229             : 
     230           0 :         return 0;
     231           0 : }
     232             : 
     233             : void
     234           0 : hidmt_configure(struct hidmt *mt)
     235             : {
     236             :         struct wsmousehw *hw;
     237             : 
     238           0 :         if (mt->sc_wsmousedev == NULL)
     239           0 :                 return;
     240             : 
     241           0 :         hw = wsmouse_get_hw(mt->sc_wsmousedev);
     242           0 :         hw->type = WSMOUSE_TYPE_TOUCHPAD;
     243           0 :         hw->hw_type = (mt->sc_clickpad
     244             :             ? WSMOUSEHW_CLICKPAD : WSMOUSEHW_TOUCHPAD);
     245           0 :         hw->x_min = mt->sc_minx;
     246           0 :         hw->x_max = mt->sc_maxx;
     247           0 :         hw->y_min = mt->sc_miny;
     248           0 :         hw->y_max = mt->sc_maxy;
     249           0 :         hw->h_res = mt->sc_resx;
     250           0 :         hw->v_res = mt->sc_resy;
     251           0 :         hw->mt_slots = HIDMT_MAX_CONTACTS;
     252             : 
     253           0 :         wsmouse_configure(mt->sc_wsmousedev, NULL, 0);
     254           0 : }
     255             : 
     256             : void
     257           0 : hidmt_attach(struct hidmt *mt, const struct wsmouse_accessops *ops)
     258             : {
     259           0 :         struct wsmousedev_attach_args a;
     260             : 
     261           0 :         printf(": %spad, %d contact%s\n",
     262           0 :             (mt->sc_clickpad ? "click" : "touch"), mt->sc_num_contacts,
     263           0 :             (mt->sc_num_contacts == 1 ? "" : "s"));
     264             : 
     265           0 :         a.accessops = ops;
     266           0 :         a.accesscookie = mt->sc_device;
     267           0 :         mt->sc_wsmousedev = config_found(mt->sc_device, &a, wsmousedevprint);
     268           0 :         hidmt_configure(mt);
     269           0 : }
     270             : 
     271             : int
     272           0 : hidmt_detach(struct hidmt *mt, int flags)
     273             : {
     274             :         int rv = 0;
     275             : 
     276           0 :         if (mt->sc_wsmousedev != NULL)
     277           0 :                 rv = config_detach(mt->sc_wsmousedev, flags);
     278             : 
     279           0 :         return (rv);
     280             : }
     281             : 
     282             : int
     283           0 : hidmt_set_input_mode(struct hidmt *mt, uint16_t mode)
     284             : {
     285           0 :         if (mt->hidev_report_type_conv == NULL)
     286           0 :                 panic("no report type conversion function");
     287             : 
     288           0 :         return mt->hidev_set_report(mt->sc_device,
     289           0 :             mt->hidev_report_type_conv(hid_feature),
     290           0 :             mt->sc_rep_config, &mode, sizeof(mode));
     291             : }
     292             : 
     293             : void
     294           0 : hidmt_input(struct hidmt *mt, uint8_t *data, u_int len)
     295             : {
     296             :         struct hidmt_data *hi;
     297             :         struct hidmt_contact hc;
     298             :         int32_t d, firstu = 0;
     299             :         int contactcount = 0, seencontacts = 0, tips = 0, i, s, z;
     300             : 
     301           0 :         if (len != mt->sc_rep_input_size) {
     302             :                 DPRINTF(("%s: %s: length %d not %d, ignoring\n",
     303             :                     mt->sc_device->dv_xname, __func__, len,
     304             :                     mt->sc_rep_input_size));
     305           0 :                 return;
     306             :         }
     307             : 
     308             :         /*
     309             :          * "In Parallel mode, devices report all contact information in a
     310             :          * single packet. Each physical contact is represented by a logical
     311             :          * collection that is embedded in the top-level collection."
     312             :          *
     313             :          * Since additional contacts that were not present will still be in the
     314             :          * report with contactid=0 but contactids are zero-based, find
     315             :          * contactcount first.
     316             :          */
     317           0 :         SIMPLEQ_FOREACH(hi, &mt->sc_inputs, entry) {
     318           0 :                 if (hi->usage == HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACTCOUNT))
     319           0 :                         contactcount = hid_get_udata(data, len, &hi->loc);
     320             :         }
     321             : 
     322           0 :         if (contactcount)
     323           0 :                 mt->sc_cur_contactcount = contactcount;
     324             :         else {
     325             :                 /*
     326             :                 * "In Hybrid mode, the number of contacts that can be reported
     327             :                 * in one report is less than the maximum number of contacts
     328             :                 * that the device supports. For example, a device that supports
     329             :                 * a maximum of 4 concurrent physical contacts, can set up its
     330             :                 * top-level collection to deliver a maximum of two contacts in
     331             :                 * one report. If four contact points are present, the device
     332             :                 * can break these up into two serial reports that deliver two
     333             :                 * contacts each.
     334             :                 *
     335             :                 * "When a device delivers data in this manner, the Contact
     336             :                 * Count usage value in the first report should reflect the
     337             :                 * total number of contacts that are being delivered in the
     338             :                 * hybrid reports. The other serial reports should have a
     339             :                 * contact count of zero (0)."
     340             :                 */
     341           0 :                 contactcount = mt->sc_cur_contactcount;
     342             :         }
     343             : 
     344           0 :         if (!contactcount) {
     345             :                 DPRINTF(("%s: %s: no contactcount in report\n",
     346             :                     mt->sc_device->dv_xname, __func__));
     347           0 :                 return;
     348             :         }
     349             : 
     350             :         /*
     351             :          * Walk through each input we know about and fetch its data from the
     352             :          * report, storing it in a temporary contact.  Once we see our first
     353             :          * usage again, we'll know we saw all usages being presented for that
     354             :          * contact.
     355             :          */
     356             :         bzero(&hc, sizeof(struct hidmt_contact));
     357           0 :         SIMPLEQ_FOREACH(hi, &mt->sc_inputs, entry) {
     358           0 :                 d = hid_get_udata(data, len, &hi->loc);
     359             : 
     360           0 :                 if (firstu && hi->usage == firstu) {
     361           0 :                         if (seencontacts < contactcount) {
     362             :                                 hc.seen = 1;
     363           0 :                                 i = wsmouse_id_to_slot(
     364           0 :                                     mt->sc_wsmousedev, hc.contactid);
     365           0 :                                 if (i >= 0)
     366           0 :                                         memcpy(&mt->sc_contacts[i], &hc,
     367             :                                             sizeof(struct hidmt_contact));
     368           0 :                                 seencontacts++;
     369           0 :                         }
     370             : 
     371             :                         bzero(&hc, sizeof(struct hidmt_contact));
     372           0 :                 }
     373           0 :                 else if (!firstu)
     374           0 :                         firstu = hi->usage;
     375             : 
     376           0 :                 switch (hi->usage) {
     377             :                 case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_X):
     378             :                         hc.x = d;
     379           0 :                         break;
     380             :                 case HID_USAGE2(HUP_GENERIC_DESKTOP, HUG_Y):
     381           0 :                         if (mt->sc_flags & HIDMT_REVY)
     382           0 :                                 hc.y = mt->sc_maxy - d;
     383             :                         else
     384             :                                 hc.y = d;
     385             :                         break;
     386             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_TIP_SWITCH):
     387             :                         hc.tip = d;
     388           0 :                         if (d)
     389           0 :                                 tips++;
     390             :                         break;
     391             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_CONFIDENCE):
     392             :                         hc.confidence = d;
     393           0 :                         break;
     394             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_WIDTH):
     395             :                         hc.width = d;
     396           0 :                         break;
     397             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_HEIGHT):
     398             :                         hc.height = d;
     399           0 :                         break;
     400             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACTID):
     401             :                         hc.contactid = d;
     402           0 :                         break;
     403             : 
     404             :                 /* these will only appear once per report */
     405             :                 case HID_USAGE2(HUP_DIGITIZERS, HUD_CONTACTCOUNT):
     406           0 :                         if (d)
     407           0 :                                 contactcount = d;
     408             :                         break;
     409             :                 case HID_USAGE2(HUP_BUTTON, 0x01):
     410           0 :                         mt->sc_button = (d != 0);
     411           0 :                         break;
     412             :                 }
     413             :         }
     414           0 :         if (seencontacts < contactcount) {
     415             :                 hc.seen = 1;
     416           0 :                 i = wsmouse_id_to_slot(mt->sc_wsmousedev, hc.contactid);
     417           0 :                 if (i >= 0)
     418           0 :                         memcpy(&mt->sc_contacts[i], &hc,
     419             :                             sizeof(struct hidmt_contact));
     420             :                 seencontacts++;
     421           0 :         }
     422             : 
     423           0 :         s = spltty();
     424           0 :         wsmouse_buttons(mt->sc_wsmousedev, mt->sc_button);
     425           0 :         for (i = 0; i < HIDMT_MAX_CONTACTS; i++) {
     426           0 :                 if (!mt->sc_contacts[i].seen)
     427             :                         continue;
     428             : 
     429           0 :                 mt->sc_contacts[i].seen = 0;
     430             : 
     431             :                 DPRINTF(("%s: %s: contact %d of %d: id %d, x %d, y %d, "
     432             :                     "touch %d, confidence %d, width %d, height %d "
     433             :                     "(button %d)\n",
     434             :                     mt->sc_device->dv_xname, __func__,
     435             :                     i + 1, contactcount,
     436             :                     mt->sc_contacts[i].contactid,
     437             :                     mt->sc_contacts[i].x,
     438             :                     mt->sc_contacts[i].y,
     439             :                     mt->sc_contacts[i].tip,
     440             :                     mt->sc_contacts[i].confidence,
     441             :                     mt->sc_contacts[i].width,
     442             :                     mt->sc_contacts[i].height,
     443             :                     mt->sc_button));
     444             : 
     445           0 :                 if (mt->sc_contacts[i].tip && !mt->sc_contacts[i].confidence)
     446             :                         continue;
     447             : 
     448             :                 /* Report width as pressure. */
     449           0 :                 z = (mt->sc_contacts[i].tip
     450           0 :                     ? imax(mt->sc_contacts[i].width, 50) : 0);
     451             : 
     452           0 :                 wsmouse_mtstate(mt->sc_wsmousedev,
     453           0 :                     i, mt->sc_contacts[i].x, mt->sc_contacts[i].y, z);
     454           0 :         }
     455           0 :         wsmouse_input_sync(mt->sc_wsmousedev);
     456             : 
     457           0 :         splx(s);
     458           0 : }
     459             : 
     460             : int
     461           0 : hidmt_enable(struct hidmt *mt)
     462             : {
     463           0 :         if (mt->sc_enabled)
     464           0 :                 return EBUSY;
     465             : 
     466           0 :         mt->sc_enabled = 1;
     467             : 
     468           0 :         return 0;
     469           0 : }
     470             : 
     471             : int
     472           0 : hidmt_ioctl(struct hidmt *mt, u_long cmd, caddr_t data, int flag,
     473             :     struct proc *p)
     474             : {
     475           0 :         struct wsmouse_calibcoords *wsmc = (struct wsmouse_calibcoords *)data;
     476             :         int wsmode;
     477             : 
     478           0 :         switch (cmd) {
     479             :         case WSMOUSEIO_GTYPE: {
     480           0 :                 struct wsmousehw *hw = wsmouse_get_hw(mt->sc_wsmousedev);
     481           0 :                 *(u_int *)data = hw->type;
     482             :                 break;
     483             :         }
     484             : 
     485             :         case WSMOUSEIO_GCALIBCOORDS:
     486           0 :                 wsmc->minx = mt->sc_minx;
     487           0 :                 wsmc->maxx = mt->sc_maxx;
     488           0 :                 wsmc->miny = mt->sc_miny;
     489           0 :                 wsmc->maxy = mt->sc_maxy;
     490           0 :                 wsmc->swapxy = 0;
     491           0 :                 wsmc->resx = mt->sc_resx;
     492           0 :                 wsmc->resy = mt->sc_resy;
     493           0 :                 break;
     494             : 
     495             :         case WSMOUSEIO_SETMODE:
     496           0 :                 wsmode = *(u_int *)data;
     497           0 :                 if (wsmode != WSMOUSE_COMPAT && wsmode != WSMOUSE_NATIVE) {
     498           0 :                         printf("%s: invalid mode %d\n",
     499           0 :                             mt->sc_device->dv_xname, wsmode);
     500           0 :                         return (EINVAL);
     501             :                 }
     502             : 
     503             :                 DPRINTF(("%s: changing mode to %s\n", mt->sc_device->dv_xname,
     504             :                     (wsmode == WSMOUSE_COMPAT ? "compat" : "native")));
     505             : 
     506           0 :                 wsmouse_set_mode(mt->sc_wsmousedev, wsmode);
     507             : 
     508           0 :                 break;
     509             : 
     510             :         default:
     511           0 :                 return -1;
     512             :         }
     513             : 
     514           0 :         return 0;
     515           0 : }
     516             : 
     517             : void
     518           0 : hidmt_disable(struct hidmt *mt)
     519             : {
     520           0 :         mt->sc_enabled = 0;
     521           0 : }

Generated by: LCOV version 1.13