36#include <sys/kernel.h>
37#include <sys/malloc.h>
38#include <sys/module.h>
45#include <sys/selinfo.h>
47#include <sys/sysctl.h>
49#include <dev/hid/hid.h>
58#define USB_DEBUG_VAR wsp_debug
62#include <dev/evdev/input.h>
63#include <dev/evdev/evdev.h>
68#define WSP_DRIVER_NAME "wsp"
69#define WSP_BUFFER_MAX 1024
71#define WSP_CLAMP(x,low,high) do { \
74 else if ((x) > (high)) \
79static SYSCTL_NODE(_hw_usb, OID_AUTO, wsp, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
84 WSP_LLEVEL_DISABLED = 0,
89static int wsp_debug = WSP_LLEVEL_ERROR;
92 &wsp_debug, WSP_LLEVEL_ERROR,
"WSP debug level");
110 .pressure_touch_threshold = 50,
111 .pressure_untouch_threshold = 10,
112 .pressure_tap_threshold = 120,
113 .scr_hor_threshold = 20,
114 .enable_single_tap_clicks = 1,
130SYSCTL_INT(_hw_usb_wsp, OID_AUTO, scale_factor, CTLFLAG_RWTUN,
136SYSCTL_INT(_hw_usb_wsp, OID_AUTO, pressure_touch_threshold, CTLFLAG_RWTUN,
138SYSCTL_INT(_hw_usb_wsp, OID_AUTO, pressure_untouch_threshold, CTLFLAG_RWTUN,
140SYSCTL_INT(_hw_usb_wsp, OID_AUTO, pressure_tap_threshold, CTLFLAG_RWTUN,
142SYSCTL_INT(_hw_usb_wsp, OID_AUTO, scr_hor_threshold, CTLFLAG_RWTUN,
144SYSCTL_INT(_hw_usb_wsp, OID_AUTO, enable_single_tap_clicks, CTLFLAG_RWTUN,
184#define FINGER_TYPE1 (13 * 2)
185#define FINGER_TYPE2 (15 * 2)
186#define FINGER_TYPE3 (19 * 2)
187#define FINGER_TYPE4 (23 * 2)
190#define BUTTON_TYPE2 15
191#define BUTTON_TYPE3 23
192#define BUTTON_TYPE4 31
195#define HAS_INTEGRATED_BUTTON 1
198#define FSIZE_TYPE1 (14 * 2)
199#define FSIZE_TYPE2 (14 * 2)
200#define FSIZE_TYPE3 (14 * 2)
201#define FSIZE_TYPE4 (15 * 2)
226 .um_switch_on = 0x01,
227 .um_switch_off = 0x08,
239 .um_switch_on = 0x01,
240 .um_switch_off = 0x08,
259 .um_switch_on = 0x01,
260 .um_switch_off = 0x00,
299#define MAX_FINGERS MAX_MT_SLOTS
301#define MAX_FINGERS 16
303#define SIZEOF_FINGER sizeof(struct tp_finger)
304#define SIZEOF_ALL_FINGERS (MAX_FINGERS * SIZEOF_FINGER)
305#define MAX_FINGER_ORIENTATION 16384
307#if (WSP_BUFFER_MAX < ((MAX_FINGERS * FSIZE_TYPE4) + FINGER_TYPE4))
308#error "WSP_BUFFER_MAX is too small"
347#define SN_PRESSURE 45
357 .x = {
SN_COORD, -4824, 5342, 105 },
366 .x = {
SN_COORD, -4824, 4824, 105 },
375 .x = {
SN_COORD, -4460, 5166, 105 },
384 .x = {
SN_COORD, -4620, 5140, 105 },
393 .x = {
SN_COORD, -4616, 5112, 105 },
402 .x = {
SN_COORD, -4415, 5050, 105 },
411 .x = {
SN_COORD, -4620, 5140, 105 },
420 .x = {
SN_COORD, -4750, 5280, 105 },
429 .x = {
SN_COORD, -4620, 5140, 105 },
438 .x = {
SN_COORD, -4750, 5280, 105 },
447 .x = {
SN_COORD, -4750, 5280, 105 },
456 .x = {
SN_COORD, -4620, 5140, 105 },
465 .x = {
SN_COORD, -4828, 5345, 105 },
471#define WSP_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
541#define WSP_FIFO_BUF_SIZE 8
542#define WSP_FIFO_QUEUE_MAXLEN 50
558 struct evdev_dev *sc_evdev;
566#define WSP_ENABLED 0x01
567#define WSP_EVDEV_OPENED 0x02
573#define WSP_UNTOUCH 0x00
574#define WSP_FIRST_TOUCH 0x01
575#define WSP_SECOND_TOUCH 0x02
576#define WSP_TOUCHING 0x04
583#define WSP_DZ_MAX_COUNT 32
592#define WSP_TAP_THRESHOLD 3
593#define WSP_TAP_MAX_COUNT 20
595#define MAX_DISTANCE 2500
599#define WSP_SCR_NONE 0
624static evdev_open_t wsp_ev_open;
625static evdev_close_t wsp_ev_close;
626static const struct evdev_methods wsp_evdev_methods = {
627 .ev_open = &wsp_ev_open,
628 .ev_close = &wsp_ev_close,
664 uint8_t mode_bytes[8];
676 DPRINTF(
"Failed to read device mode (%d)\n", err);
686 pause(
"WHW", hz / 4);
703 DPRINTFN(WSP_LLEVEL_INFO,
"enabled wsp\n");
711 DPRINTFN(WSP_LLEVEL_INFO,
"disabled wsp\n");
728 if (iface == NULL || i == 3)
733 (
id->bInterfaceProtocol != 0 &&
744 return (BUS_PROBE_DEFAULT);
756 DPRINTFN(WSP_LLEVEL_INFO,
"sc=%p\n", sc);
764 sc->
tp_datalen = hid_report_size_max(d_ptr, d_len, hid_input,
769 DPRINTF(
"Invalid datalength or too big "
799 DPRINTF(
"Failed to set mode to HID MODE (%d)\n", err);
805 DPRINTF(
"failed to set mode to RAW MODE (%d)\n", err);
809 mtx_init(&sc->
sc_mutex,
"wspmtx", NULL, MTX_DEF | MTX_RECURSE);
821 UID_ROOT, GID_OPERATOR, 0644)) {
826 sc->
sc_hw.buttons = 3;
827 sc->
sc_hw.iftype = MOUSE_IF_USB;
828 sc->
sc_hw.type = MOUSE_PAD;
829 sc->
sc_hw.model = MOUSE_MODEL_GENERIC;
830 sc->
sc_mode.protocol = MOUSE_PROTO_MSC;
832 sc->
sc_mode.resolution = MOUSE_RES_UNKNOWN;
833 sc->
sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
834 sc->
sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
835 sc->
sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
841 sc->sc_evdev = evdev_alloc();
842 evdev_set_name(sc->sc_evdev, device_get_desc(
dev));
843 evdev_set_phys(sc->sc_evdev, device_get_nameunit(
dev));
847 evdev_set_methods(sc->sc_evdev, sc, &wsp_evdev_methods);
848 evdev_support_prop(sc->sc_evdev, INPUT_PROP_POINTER);
849 evdev_support_event(sc->sc_evdev, EV_SYN);
850 evdev_support_event(sc->sc_evdev, EV_ABS);
851 evdev_support_event(sc->sc_evdev, EV_KEY);
853#define WSP_SUPPORT_ABS(evdev, code, param) \
854 evdev_support_abs((evdev), (code), (param).min, (param).max, \
855 ((param).max - (param).min) / (param).snratio, 0, \
856 (param).size != 0 ? ((param).max - (param).min) / (param).size : 0);
859 WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_X, sc->
sc_params->
x);
860 WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_POSITION_Y, sc->
sc_params->
y);
862 WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_PRESSURE, sc->
sc_params->
p);
864 WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MAJOR, sc->
sc_params->
w);
865 WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_TOUCH_MINOR, sc->
sc_params->
w);
867 WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_WIDTH_MAJOR, sc->
sc_params->
w);
868 WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_WIDTH_MINOR, sc->
sc_params->
w);
870 WSP_SUPPORT_ABS(sc->sc_evdev, ABS_MT_ORIENTATION, sc->
sc_params->
o);
872 evdev_support_key(sc->sc_evdev, BTN_LEFT);
874 evdev_support_prop(sc->sc_evdev, INPUT_PROP_BUTTONPAD);
876 evdev_support_abs(sc->sc_evdev, ABS_MT_SLOT,
878 evdev_support_abs(sc->sc_evdev, ABS_MT_TRACKING_ID,
880 evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_TRACK);
881 evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_AUTOREL);
883 evdev_set_flag(sc->sc_evdev, EVDEV_FLAG_MT_STCOMPAT);
885 err = evdev_register(sc->sc_evdev);
912 evdev_free(sc->sc_evdev);
959 if ((len < params->tp->offset + params->
tp->
fsize) ||
961 DPRINTFN(WSP_LLEVEL_INFO,
"Invalid length: %d, %x, %x\n",
962 len, sc->tp_data[0], sc->tp_data[1]);
966 if (len < sc->tp_datalen) {
975 ntouch = sc->tp_data[params->
tp->
button - 1];
985 for (i = 0; i != ntouch; i++) {
988 if (le16toh(0x1234) != 0x1234) {
1002 DPRINTFN(WSP_LLEVEL_INFO,
1003 "[%d]ibt=%d, taps=%d, o=%4d, ax=%5d, ay=%5d, "
1004 "rx=%5d, ry=%5d, tlmaj=%4d, tlmin=%4d, ot=%4x, "
1005 "tchmaj=%4d, tchmin=%4d, presure=%4d, m=%4x\n",
1013 if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE && f->
touch_major != 0) {
1014 union evdev_mt_slot slot_data = {
1025 evdev_mt_push_slot(sc->sc_evdev,
slot, &slot_data);
1032 if (evdev_rcpt_mask & EVDEV_RCPT_HW_MOUSE) {
1033 evdev_push_key(sc->sc_evdev, BTN_LEFT, ibt);
1034 evdev_sync(sc->sc_evdev);
1037 sc->
sc_status.flags &= ~MOUSE_POSCHANGED;
1038 sc->
sc_status.flags &= ~MOUSE_STDBUTTONSCHANGED;
1044 sc->
sc_status.button |= MOUSE_BUTTON3DOWN;
1046 sc->
sc_status.button |= MOUSE_BUTTON2DOWN;
1048 sc->
sc_status.button |= MOUSE_BUTTON1DOWN;
1053 if (sc->
ntaps < ntouch) {
1090 switch (sc->
ntaps) {
1094 DPRINTFN(WSP_LLEVEL_INFO,
"LEFT CLICK!\n");
1098 DPRINTFN(WSP_LLEVEL_INFO,
"sum_x=%5d, sum_y=%5d\n",
1103 DPRINTFN(WSP_LLEVEL_INFO,
"RIGHT CLICK!\n");
1146 DPRINTFN(WSP_LLEVEL_INFO,
"Fist pre_x=%5d, pre_y=%5d\n",
1169 if (sc->
ibtn != 0 && ntouch == 1 &&
1174 if (ntouch == 2 && sc->
sc_status.button != 0) {
1201 DPRINTFN(WSP_LLEVEL_INFO,
"dx=%5d, dy=%5d, mov=%5d\n",
1223 if (ntouch == 2 && sc->
sc_status.button == 0) {
1228 DPRINTFN(WSP_LLEVEL_INFO,
"scr_mode=%5d, count=%d, dx_sum=%d, dy_sum=%d\n",
1246 abs(dx) < 3 && abs(dy) < 3 && abs(dz) < 3)
1251 sc->
sc_status.flags |= MOUSE_POSCHANGED;
1252 DPRINTFN(WSP_LLEVEL_INFO,
"dx=%5d, dy=%5d, dz=%5d, sc_touch=%x, btn=%x\n",
1267 if (ntouch == 2 && sc->
sc_status.button != 0) {
1296 uint32_t buttons_in)
1298 uint32_t buttons_out;
1302 dx = imax(dx, -256);
1304 dy = imax(dy, -256);
1306 dz = imax(dz, -128);
1308 buttons_out = MOUSE_MSC_BUTTONS;
1309 if (buttons_in & MOUSE_BUTTON1DOWN)
1310 buttons_out &= ~MOUSE_MSC_BUTTON1UP;
1311 else if (buttons_in & MOUSE_BUTTON2DOWN)
1312 buttons_out &= ~MOUSE_MSC_BUTTON2UP;
1313 else if (buttons_in & MOUSE_BUTTON3DOWN)
1314 buttons_out &= ~MOUSE_MSC_BUTTON3UP;
1317 buf[0] = sc->
sc_mode.syncmask[1];
1318 buf[0] |= buttons_out;
1321 buf[3] = dx - (dx >> 1);
1322 buf[4] = dy - (dy >> 1);
1326 buf[6] = dz - (dz >> 1);
1327 buf[7] = (((~buttons_in) >> 3) & MOUSE_SYS_EXTBUTTONS);
1374 DPRINTFN(WSP_LLEVEL_INFO,
"\n");
1379 if (fflags & FREAD) {
1393 sc->
sc_fflags |= fflags & (FREAD | FWRITE);
1402 if (fflags & FREAD) {
1410 sc->
sc_fflags &= ~(fflags & (FREAD | FWRITE));
1434wsp_ev_open(
struct evdev_dev *evdev)
1436 struct wsp_softc *sc = evdev_get_softc(evdev);
1452wsp_ev_close(
struct evdev_dev *evdev)
1454 struct wsp_softc *sc = evdev_get_softc(evdev);
1476 case MOUSE_GETHWINFO:
1483 mode = *(mousemode_t *)
addr;
1485 if (mode.level == -1)
1488 else if ((mode.level < 0) || (mode.level > 1)) {
1492 sc->
sc_mode.level = mode.level;
1494 sc->
sc_hw.buttons = 3;
1497 sc->
sc_mode.protocol = MOUSE_PROTO_MSC;
1498 sc->
sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
1499 sc->
sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
1500 sc->
sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
1501 }
else if (sc->
sc_mode.level == 1) {
1502 sc->
sc_mode.protocol = MOUSE_PROTO_SYSMOUSE;
1503 sc->
sc_mode.packetsize = MOUSE_SYS_PACKETSIZE;
1504 sc->
sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK;
1505 sc->
sc_mode.syncmask[1] = MOUSE_SYS_SYNC;
1509 case MOUSE_GETLEVEL:
1512 case MOUSE_SETLEVEL:
1513 if (*(
int *)
addr < 0 || *(
int *)
addr > 1) {
1518 sc->
sc_hw.buttons = 3;
1521 sc->
sc_mode.protocol = MOUSE_PROTO_MSC;
1522 sc->
sc_mode.packetsize = MOUSE_MSC_PACKETSIZE;
1523 sc->
sc_mode.syncmask[0] = MOUSE_MSC_SYNCMASK;
1524 sc->
sc_mode.syncmask[1] = MOUSE_MSC_SYNC;
1525 }
else if (sc->
sc_mode.level == 1) {
1526 sc->
sc_mode.protocol = MOUSE_PROTO_SYSMOUSE;
1527 sc->
sc_mode.packetsize = MOUSE_SYS_PACKETSIZE;
1528 sc->
sc_mode.syncmask[0] = MOUSE_SYS_SYNCMASK;
1529 sc->
sc_mode.syncmask[1] = MOUSE_SYS_SYNC;
1533 case MOUSE_GETSTATUS:{
1534 mousestatus_t *
status = (mousestatus_t *)
addr;
1544 status->flags |= MOUSE_POSCHANGED;
1546 status->flags |= MOUSE_BUTTONSCHANGED;
enum usb_hc_mode usb_mode
struct usbd_lookup_info info
struct usb_device * device
struct usb_interface_descriptor * idesc
const struct wsp_dev_params * sc_params
struct usb_xfer * sc_xfer[WSP_N_TRANSFER]
int16_t pos_x[MAX_FINGERS]
uint8_t tp_data[WSP_BUFFER_MAX] __aligned(4)
int16_t pos_y[MAX_FINGERS]
struct usb_fifo_sc sc_fifo
struct tp_finger * index[MAX_FINGERS]
struct usb_device * sc_usb_device
int enable_single_tap_clicks
int pressure_touch_threshold
int pressure_untouch_threshold
int pressure_tap_threshold
void usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset, void *ptr, usb_frlength_t len)
const char * usb_get_serial(struct usb_device *udev)
struct usb_interface * usbd_get_iface(struct usb_device *udev, uint8_t iface_index)
const char * usbd_errstr(usb_error_t err)
usb_error_t usbd_req_get_hid_desc(struct usb_device *udev, struct mtx *mtx, void **descp, uint16_t *sizep, struct malloc_type *mem, uint8_t iface_index)
int usbd_lookup_id_by_uaa(const struct usb_device_id *id, usb_size_t sizeof_id, struct usb_attach_arg *uaa)
usb_error_t usbd_req_set_report(struct usb_device *udev, struct mtx *mtx, void *data, uint16_t len, uint8_t iface_index, uint8_t type, uint8_t id)
usb_error_t usbd_req_get_report(struct usb_device *udev, struct mtx *mtx, void *data, uint16_t len, uint8_t iface_index, uint8_t type, uint8_t id)
void usbd_transfer_submit(struct usb_xfer *xfer)
void usbd_transfer_unsetup(struct usb_xfer **pxfer, uint16_t n_setup)
void usbd_xfer_set_frame_len(struct usb_xfer *xfer, usb_frcount_t frindex, usb_frlength_t len)
struct usb_page_cache * usbd_xfer_get_frame(struct usb_xfer *xfer, usb_frcount_t frindex)
usb_error_t usbd_transfer_setup(struct usb_device *udev, const uint8_t *ifaces, struct usb_xfer **ppxfer, const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx)
void usbd_transfer_start(struct usb_xfer *xfer)
void * usbd_xfer_softc(struct usb_xfer *xfer)
void usbd_xfer_set_stall(struct usb_xfer *xfer)
void usbd_xfer_set_interval(struct usb_xfer *xfer, int i)
void usbd_transfer_stop(struct usb_xfer *xfer)
void usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen, int *aframes, int *nframes)
void device_set_usb_desc(device_t dev)
int usb_fifo_alloc_buffer(struct usb_fifo *f, uint32_t bufsize, uint16_t nbuf)
int() usb_fifo_ioctl_t(struct usb_fifo *fifo, u_long cmd, void *addr, int fflags)
void * usb_fifo_softc(struct usb_fifo *fifo)
void() usb_fifo_close_t(struct usb_fifo *fifo, int fflags)
void usb_fifo_detach(struct usb_fifo_sc *f_sc)
void usb_fifo_put_data_linear(struct usb_fifo *fifo, void *ptr, usb_size_t len, uint8_t what)
int usb_fifo_attach(struct usb_device *udev, void *priv_sc, struct mtx *priv_mtx, struct usb_fifo_methods *pm, struct usb_fifo_sc *f_sc, uint16_t unit, int16_t subunit, uint8_t iface_index, uid_t uid, gid_t gid, int mode)
@ USB_ERR_NORMAL_COMPLETION
void() usb_fifo_cmd_t(struct usb_fifo *fifo)
void usb_fifo_free_buffer(struct usb_fifo *f)
void usb_fifo_reset(struct usb_fifo *f)
#define USB_ST_TRANSFERRED
void() usb_callback_t(struct usb_xfer *, usb_error_t)
int() usb_fifo_open_t(struct usb_fifo *fifo, int fflags)
#define STRUCT_USB_HOST_ID
#define USB_GET_DRIVER_INFO(did)
#define USB_GET_STATE(xfer)
uint32_t usb_fifo_put_bytes_max(struct usb_fifo *fifo)
#define UHID_FEATURE_REPORT
#define WSP_FIFO_BUF_SIZE
USB_PNP_HOST_INFO(wsp_devs)
SYSCTL_INT(_hw_usb_wsp, OID_AUTO, scale_factor, CTLFLAG_RWTUN, &wsp_tuning.scale_factor, 0, "movement scale factor")
static void wsp_stop_read(struct wsp_softc *sc)
#define WSP_TAP_MAX_COUNT
static void wsp_runing_rangecheck(struct wsp_tuning *ptun)
static const struct usb_config wsp_config[WSP_N_TRANSFER]
#define WSP_CLAMP(x, low, high)
static int wsp_enable(struct wsp_softc *sc)
static usb_fifo_close_t wsp_close
static devclass_t wsp_devclass
DRIVER_MODULE(wsp, uhub, wsp_driver, wsp_devclass, NULL, 0)
static usb_fifo_ioctl_t wsp_ioctl
static device_probe_t wsp_probe
static SYSCTL_NODE(_hw_usb, OID_AUTO, wsp, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "USB wsp")
static usb_fifo_open_t wsp_open
static void wsp_add_to_queue(struct wsp_softc *, int, int, int, uint32_t)
static const STRUCT_USB_HOST_ID wsp_devs[]
static usb_fifo_cmd_t wsp_fifo_stop_read
static driver_t wsp_driver
MODULE_DEPEND(wsp, usb, 1, 1, 1)
static device_method_t wsp_methods[]
static device_attach_t wsp_attach
static void wsp_reset_buf(struct wsp_softc *sc)
static usb_fifo_cmd_t wsp_fifo_start_read
static struct usb_fifo_methods wsp_fifo_methods
#define WSP_FIFO_QUEUE_MAXLEN
static struct wsp_tuning wsp_tuning
#define WSP_TAP_THRESHOLD
static usb_error_t wsp_set_device_mode(struct wsp_softc *sc, uint8_t on)
#define MAX_FINGER_ORIENTATION
static void wsp_start_read(struct wsp_softc *sc)
static device_detach_t wsp_detach
static usb_callback_t wsp_intr_callback
#define HAS_INTEGRATED_BUTTON
static void wsp_disable(struct wsp_softc *sc)