1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/usb/usba/usbai_version.h> 30 #include <sys/usb/usba.h> 31 #include <sys/usb/clients/hid/hid.h> 32 #include <sys/usb/clients/hidparser/hidparser.h> 33 34 #include <sys/stropts.h> 35 #include <sys/strsun.h> 36 #include <sys/vuid_event.h> 37 #include <sys/vuid_wheel.h> 38 #include <sys/termios.h> 39 #include <sys/termio.h> 40 #include <sys/strtty.h> 41 #include <sys/msreg.h> 42 #include <sys/msio.h> 43 44 #include <sys/usb/clients/usbms/usbms.h> 45 46 /* debugging information */ 47 static uint_t usbms_errmask = (uint_t)PRINT_MASK_ALL; 48 static uint_t usbms_errlevel = USB_LOG_L2; 49 static usb_log_handle_t usbms_log_handle; 50 51 static struct streamtab usbms_streamtab; 52 53 static struct fmodsw fsw = { 54 "usbms", 55 &usbms_streamtab, 56 D_MP | D_MTPERMOD 57 }; 58 59 /* 60 * Module linkage information for the kernel. 61 */ 62 static struct modlstrmod modlstrmod = { 63 &mod_strmodops, 64 "USB mouse streams %I%", 65 &fsw 66 }; 67 68 static struct modlinkage modlinkage = { 69 MODREV_1, 70 (void *)&modlstrmod, 71 NULL 72 }; 73 74 75 int 76 _init(void) 77 { 78 int rval = mod_install(&modlinkage); 79 80 if (rval == 0) { 81 usbms_log_handle = usb_alloc_log_hdl(NULL, "usbms", 82 &usbms_errlevel, &usbms_errmask, NULL, 0); 83 } 84 85 return (rval); 86 } 87 88 int 89 _fini(void) 90 { 91 int rval = mod_remove(&modlinkage); 92 93 if (rval == 0) { 94 usb_free_log_hdl(usbms_log_handle); 95 } 96 97 return (rval); 98 } 99 100 101 int 102 _info(struct modinfo *modinfop) 103 { 104 105 return (mod_info(&modlinkage, modinfop)); 106 } 107 108 109 /* Function prototypes */ 110 static void usbms_reioctl(void *); 111 static void usbms_ioctl(queue_t *, mblk_t *); 112 static int usbms_open(); 113 static int usbms_close(); 114 static int usbms_wput(); 115 static void usbms_rput(); 116 static void usbms_mctl_receive( 117 register queue_t *q, 118 register mblk_t *mp); 119 120 static void usbms_rserv(queue_t *q); 121 static void usbms_miocdata( 122 register queue_t *q, 123 register mblk_t *mp); 124 125 static void usbms_resched(void *); 126 127 static int usbms_getparms( 128 register Ms_parms *data, 129 usbms_state_t *usbmsp); 130 131 static int usbms_setparms( 132 register Ms_parms *data, 133 usbms_state_t *usbmsp); 134 135 static int usbms_get_screen_parms( 136 register queue_t *q, 137 register mblk_t *datap); 138 139 static void usbms_flush(usbms_state_t *usbmsp); 140 141 static void usbms_incr(void *); 142 static void usbms_input( 143 usbms_state_t *usbmsp, 144 mblk_t *mp); 145 static void usbms_rserv_vuid_button( 146 queue_t *q, 147 struct usbmouseinfo *mi, 148 mblk_t **bpaddr); 149 150 static void usbms_rserv_vuid_event_y( 151 queue_t *q, 152 struct usbmouseinfo *mi, 153 mblk_t **bpaddr); 154 static void usbms_rserv_vuid_event_x( 155 queue_t *q, 156 struct usbmouseinfo *mi, 157 mblk_t **bpaddr); 158 static void usbms_rserv_vuid_event_wheel( 159 queue_t *, 160 struct usbmouseinfo *, 161 mblk_t **, 162 ushort_t id); 163 static int usbms_check_for_wheels(usbms_state_t *); 164 static int usbms_make_copyreq( 165 mblk_t *, 166 uint_t pvtsize, 167 uint_t state, 168 uint_t reqsize, 169 uint_t contsize, 170 uint_t copytype); 171 static int usbms_service_wheel_info( 172 queue_t *, 173 mblk_t *); 174 static int usbms_service_wheel_state( 175 queue_t *, 176 mblk_t *, 177 uint_t cmd); 178 static void usbms_ack_ioctl(mblk_t *); 179 static int usbms_read_input_data_format(usbms_state_t *); 180 extern void uniqtime32(); 181 182 /* 183 * Device driver qinit functions 184 */ 185 static struct module_info usbms_mod_info = { 186 0x0ffff, /* module id number */ 187 "usbms", /* module name */ 188 0, /* min packet size accepted */ 189 INFPSZ, /* max packet size accepted */ 190 512, /* hi-water mark */ 191 128 /* lo-water mark */ 192 }; 193 194 /* read side queue information structure */ 195 static struct qinit rinit = { 196 (int (*)())usbms_rput, /* put procedure not needed */ 197 (int (*)())usbms_rserv, /* service procedure */ 198 usbms_open, /* called on startup */ 199 usbms_close, /* called on finish */ 200 NULL, /* for future use */ 201 &usbms_mod_info, /* module information structure */ 202 NULL /* module statistics structure */ 203 }; 204 205 /* write side queue information structure */ 206 static struct qinit winit = { 207 usbms_wput, /* put procedure */ 208 NULL, /* no service proecedure needed */ 209 NULL, /* open not used on write side */ 210 NULL, /* close not used on write side */ 211 NULL, /* for future use */ 212 &usbms_mod_info, /* module information structure */ 213 NULL /* module statistics structure */ 214 }; 215 216 static struct streamtab usbms_streamtab = { 217 &rinit, 218 &winit, 219 NULL, /* not a MUX */ 220 NULL /* not a MUX */ 221 }; 222 223 /* 224 * Message when overrun circular buffer 225 */ 226 static int overrun_msg; 227 228 /* Increment when overrun circular buffer */ 229 static int overrun_cnt; 230 231 extern int hz; 232 233 /* 234 * Mouse buffer size in bytes. Place here as variable so that one could 235 * massage it using adb if it turns out to be too small. 236 */ 237 static uint16_t usbms_buf_bytes = USBMS_BUF_BYTES; 238 239 240 /* 241 * Regular STREAMS Entry points 242 */ 243 244 /* 245 * usbms_open() : 246 * open() entry point for the USB mouse module. 247 */ 248 /*ARGSUSED*/ 249 static int 250 usbms_open(queue_t *q, 251 dev_t *devp, 252 int flag, 253 int sflag, 254 cred_t *credp) 255 256 { 257 register struct usbmousebuf *mousebufp; 258 register struct ms_softc *msd_soft; 259 usbms_state_t *usbmsp; 260 struct iocblk mctlmsg; 261 mblk_t *mctl_ptr; 262 263 264 /* Clone opens are not allowed */ 265 if (sflag != MODOPEN) 266 return (EINVAL); 267 268 /* If the module is already open, just return */ 269 if (q->q_ptr) { 270 return (0); 271 } 272 273 /* allocate usbms state structure */ 274 usbmsp = kmem_zalloc(sizeof (usbms_state_t), KM_SLEEP); 275 276 q->q_ptr = usbmsp; 277 WR(q)->q_ptr = usbmsp; 278 279 usbmsp->usbms_rq_ptr = q; 280 usbmsp->usbms_wq_ptr = WR(q); 281 282 qprocson(q); 283 284 /* 285 * Set up private data. 286 */ 287 usbmsp->usbms_state = USBMS_WAIT_BUTN; 288 usbmsp->usbms_iocpending = NULL; 289 usbmsp->usbms_jitter_thresh = USBMS_JITTER_THRESH; 290 usbmsp->usbms_speedlimit = USBMS_SPEEDLIMIT; 291 usbmsp->usbms_speedlaw = USBMS_SPEEDLAW; 292 usbmsp->usbms_speed_count = USBMS_SPEED_COUNT; 293 294 msd_soft = &usbmsp->usbms_softc; 295 296 /* 297 * Initially set the format to MS_VUID_FORMAT 298 */ 299 msd_soft->ms_readformat = MS_VUID_FORMAT; 300 301 /* 302 * Allocate buffer and initialize data. 303 */ 304 msd_soft->ms_bufbytes = usbms_buf_bytes; 305 mousebufp = kmem_zalloc((uint_t)msd_soft->ms_bufbytes, 306 KM_SLEEP); 307 308 /* Truncation will happen */ 309 mousebufp->mb_size = (uint16_t)((msd_soft->ms_bufbytes - 310 sizeof (struct usbmousebuf)) / 311 sizeof (struct usbmouseinfo)); 312 mousebufp->mb_info = (struct usbmouseinfo *)((char *)mousebufp + 313 sizeof (struct usbmousebuf)); 314 usbmsp->usbms_buf = mousebufp; 315 msd_soft->ms_vuidaddr = VKEY_FIRST; 316 usbmsp->usbms_jittertimeout = JITTER_TIMEOUT; 317 318 /* request hid report descriptor from HID */ 319 mctlmsg.ioc_cmd = HID_GET_PARSER_HANDLE; 320 mctlmsg.ioc_count = 0; 321 322 mctl_ptr = usba_mk_mctl(mctlmsg, NULL, 0); 323 if (mctl_ptr == NULL) { 324 qprocsoff(q); 325 kmem_free(usbmsp->usbms_buf, msd_soft->ms_bufbytes); 326 kmem_free(usbmsp, sizeof (usbms_state_t)); 327 328 return (ENOMEM); 329 } 330 331 usbmsp->usbms_flags |= USBMS_QWAIT; 332 putnext(usbmsp->usbms_wq_ptr, mctl_ptr); 333 334 /* 335 * Now that signal has been sent, wait for report descriptor. Cleanup 336 * if user signals in the mean time (as when this gets opened in an 337 * inappropriate context and the user types a ^C). 338 */ 339 while (usbmsp->usbms_flags & USBMS_QWAIT) { 340 341 if (qwait_sig(q) == 0) { 342 qprocsoff(q); 343 kmem_free(usbmsp->usbms_buf, msd_soft->ms_bufbytes); 344 kmem_free(usbmsp, sizeof (usbms_state_t)); 345 346 return (EINTR); 347 } 348 } 349 350 if (usbmsp->usbms_report_descr_handle != NULL) { 351 if (hidparser_get_usage_attribute( 352 usbmsp->usbms_report_descr_handle, 353 0, 354 HIDPARSER_ITEM_INPUT, 355 USBMS_USAGE_PAGE_BUTTON, 356 0, 357 HIDPARSER_ITEM_REPORT_COUNT, 358 (int32_t *)&usbmsp->usbms_num_buttons) == 359 HIDPARSER_SUCCESS) { 360 USB_DPRINTF_L2(PRINT_MASK_ALL, 361 usbms_log_handle, "Num of buttons is : %d", 362 usbmsp->usbms_num_buttons); 363 } else { 364 USB_DPRINTF_L3(PRINT_MASK_OPEN, 365 usbms_log_handle, 366 "hidparser_get_usage_attribute failed : " 367 "Set to default number of buttons(3)."); 368 369 usbmsp->usbms_num_buttons = USB_MS_DEFAULT_BUTTON_NO; 370 } 371 } else { 372 USB_DPRINTF_L1(PRINT_MASK_ALL, 373 usbms_log_handle, "usbms: Invalid HID " 374 "Descriptor Tree. Set to default value(3 buttons)."); 375 usbmsp->usbms_num_buttons = USB_MS_DEFAULT_BUTTON_NO; 376 } 377 378 /* check if this mouse has wheel */ 379 if (usbms_check_for_wheels(usbmsp) == USB_FAILURE) { 380 USB_DPRINTF_L2(PRINT_MASK_ALL, usbms_log_handle, 381 "No wheels detected"); 382 } else { 383 USB_DPRINTF_L2(PRINT_MASK_ALL, usbms_log_handle, 384 "Wheel detected"); 385 } 386 387 usbms_flush(usbmsp); 388 389 /* get the data format from the hid descriptor */ 390 if (usbms_read_input_data_format(usbmsp) != USB_SUCCESS) { 391 392 qprocsoff(q); 393 kmem_free(usbmsp->usbms_buf, msd_soft->ms_bufbytes); 394 kmem_free(usbmsp, sizeof (usbms_state_t)); 395 396 return (EINVAL); 397 } 398 399 usbmsp->usbms_flags |= USBMS_OPEN; 400 401 USB_DPRINTF_L3(PRINT_MASK_OPEN, usbms_log_handle, 402 "usbms_open exiting"); 403 404 return (0); 405 } 406 407 408 /* 409 * usbms_close() : 410 * close() entry point for the USB mouse module. 411 */ 412 /*ARGSUSED*/ 413 static int 414 usbms_close(queue_t *q, 415 int flag, 416 cred_t *credp) 417 { 418 usbms_state_t *usbmsp = q->q_ptr; 419 register struct ms_softc *ms = &usbmsp->usbms_softc; 420 421 USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbms_log_handle, 422 "usbms_close entering"); 423 424 qprocsoff(q); 425 426 if (usbmsp->usbms_jitter) { 427 (void) quntimeout(q, 428 (timeout_id_t)(long)usbmsp->usbms_timeout_id); 429 usbmsp->usbms_jitter = 0; 430 } 431 if (usbmsp->usbms_reioctl_id) { 432 qunbufcall(q, (bufcall_id_t)(long)usbmsp->usbms_reioctl_id); 433 usbmsp->usbms_reioctl_id = 0; 434 } 435 if (usbmsp->usbms_resched_id) { 436 qunbufcall(q, (bufcall_id_t)usbmsp->usbms_resched_id); 437 usbmsp->usbms_resched_id = 0; 438 } 439 if (usbmsp->usbms_iocpending != NULL) { 440 /* 441 * We were holding an "ioctl" response pending the 442 * availability of an "mblk" to hold data to be passed up; 443 * another "ioctl" came through, which means that "ioctl" 444 * must have timed out or been aborted. 445 */ 446 freemsg(usbmsp->usbms_iocpending); 447 usbmsp->usbms_iocpending = NULL; 448 } 449 450 451 /* Free mouse buffer */ 452 if (usbmsp->usbms_buf != NULL) { 453 kmem_free(usbmsp->usbms_buf, ms->ms_bufbytes); 454 } 455 456 kmem_free(usbmsp, sizeof (usbms_state_t)); 457 458 q->q_ptr = NULL; 459 WR(q)->q_ptr = NULL; 460 461 462 USB_DPRINTF_L3(PRINT_MASK_CLOSE, usbms_log_handle, 463 "usbms_close exiting"); 464 465 return (0); 466 } 467 468 469 /* 470 * usbms_rserv() : 471 * Read queue service routine. 472 * Turn buffered mouse events into stream messages. 473 */ 474 static void 475 usbms_rserv(queue_t *q) 476 { 477 usbms_state_t *usbmsp = q->q_ptr; 478 struct ms_softc *ms; 479 struct usbmousebuf *b; 480 struct usbmouseinfo *mi; 481 mblk_t *bp; 482 ushort_t i, loop; 483 uchar_t nbutt = (uchar_t)usbmsp->usbms_num_buttons; 484 485 ms = &usbmsp->usbms_softc; 486 b = usbmsp->usbms_buf; 487 488 USB_DPRINTF_L3(PRINT_MASK_SERV, usbms_log_handle, 489 "usbms_rserv entering"); 490 491 while (canputnext(q) && ms->ms_oldoff != b->mb_off) { 492 mi = &b->mb_info[ms->ms_oldoff]; 493 switch (ms->ms_readformat) { 494 495 case MS_3BYTE_FORMAT: { 496 register char *cp; 497 498 if ((usbmsp->usbms_idf).xlen != 1) { 499 USB_DPRINTF_L3(PRINT_MASK_SERV, 500 usbms_log_handle, 501 "Can't set to 3 byte format. Length != 1"); 502 503 return; 504 } 505 if ((bp = allocb(3, BPRI_HI)) != NULL) { 506 cp = (char *)bp->b_wptr; 507 508 *cp++ = 0x80 | (mi->mi_buttons & 0xFF); 509 /* Update read buttons */ 510 ms->ms_prevbuttons = mi->mi_buttons; 511 512 *cp++ = (mi->mi_x & 0xFF); 513 *cp++ = ((-mi->mi_y) & 0xFF); 514 /* lower pri to avoid mouse droppings */ 515 bp->b_wptr = (uchar_t *)cp; 516 putnext(q, bp); 517 } else { 518 if (usbmsp->usbms_resched_id) { 519 qunbufcall(q, 520 (bufcall_id_t)usbmsp->usbms_resched_id); 521 } 522 usbmsp->usbms_resched_id = qbufcall(q, 523 (size_t)3, 524 (uint_t)BPRI_HI, 525 (void (*)())usbms_resched, 526 (void *) usbmsp); 527 if (usbmsp->usbms_resched_id == 0) 528 529 return; /* try again later */ 530 /* bufcall failed; just pitch this event */ 531 /* or maybe flush queue? */ 532 } 533 ms->ms_oldoff++; /* next event */ 534 535 /* circular buffer wraparound */ 536 if (ms->ms_oldoff >= b->mb_size) { 537 ms->ms_oldoff = 0; 538 } 539 break; 540 } 541 542 case MS_VUID_FORMAT: 543 default: { 544 545 do { 546 bp = NULL; 547 548 switch (ms->ms_eventstate) { 549 550 case EVENT_WHEEL: 551 loop = (usbmsp->usbms_num_wheels ? 552 1 : 0); 553 554 if (usbmsp->usbms_num_wheels) { 555 for (i = 0; i < loop; i++) { 556 usbms_rserv_vuid_event_wheel 557 (q, mi, &bp, i); 558 } 559 } 560 561 break; 562 case EVENT_BUT8: 563 case EVENT_BUT7: 564 case EVENT_BUT6: 565 case EVENT_BUT5: 566 case EVENT_BUT4: 567 case EVENT_BUT3: /* Send right button */ 568 case EVENT_BUT2: /* Send middle button */ 569 case EVENT_BUT1: /* Send left button */ 570 usbms_rserv_vuid_button(q, mi, &bp); 571 572 break; 573 case EVENT_Y: 574 usbms_rserv_vuid_event_y(q, mi, &bp); 575 576 break; 577 case EVENT_X: 578 usbms_rserv_vuid_event_x(q, mi, &bp); 579 580 break; 581 default: 582 /* start again */ 583 ms->ms_eventstate = EVENT_WHEEL; 584 585 break; 586 } 587 if (bp != NULL) { 588 /* lower pri to avoid mouse droppings */ 589 bp->b_wptr += sizeof (Firm_event); 590 putnext(q, bp); 591 } 592 if (ms->ms_eventstate == EVENT_X) { 593 ms->ms_eventstate = EVENT_WHEEL; 594 } else if (ms->ms_eventstate == EVENT_WHEEL) { 595 ms->ms_oldoff++; /* next event */ 596 /* circular buffer wraparound */ 597 if (ms->ms_oldoff >= b->mb_size) { 598 ms->ms_oldoff = 0; 599 } 600 ms->ms_eventstate = EVENT_BUT(nbutt); 601 } else 602 ms->ms_eventstate--; 603 } while (ms->ms_eventstate != EVENT_BUT(nbutt)); 604 } 605 } 606 } 607 USB_DPRINTF_L3(PRINT_MASK_SERV, usbms_log_handle, 608 "usbms_rserv exiting"); 609 } 610 611 612 /* 613 * usbms_rserv_vuid_event_wheel 614 * convert wheel data to firm events 615 */ 616 static void 617 usbms_rserv_vuid_event_wheel(queue_t *q, 618 struct usbmouseinfo *mi, 619 mblk_t **bpaddr, 620 ushort_t id) 621 { 622 Firm_event *fep; 623 mblk_t *tmp; 624 struct ms_softc *ms; 625 usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr; 626 627 if (!(usbmsp->usbms_wheel_state_bf & (1 << id))) { 628 629 return; 630 } 631 ms = &usbmsp->usbms_softc; 632 if (mi->mi_z) { 633 if ((tmp = allocb(sizeof (Firm_event), BPRI_HI)) != NULL) { 634 fep = (Firm_event *)tmp->b_wptr; 635 fep->id = vuid_id_addr(vuid_first(VUID_WHEEL)) | 636 vuid_id_offset(id); 637 fep->pair_type = FE_PAIR_NONE; 638 fep->pair = NULL; 639 fep->value = mi->mi_z; 640 fep->time = mi->mi_time; 641 *bpaddr = tmp; 642 } else { 643 if (usbmsp->usbms_resched_id) { 644 qunbufcall(q, 645 (bufcall_id_t)usbmsp->usbms_resched_id); 646 } 647 usbmsp->usbms_resched_id = 648 qbufcall(q, sizeof (Firm_event), BPRI_HI, 649 (void (*)())usbms_resched, (void *) usbmsp); 650 if (usbmsp->usbms_resched_id == 0) { 651 /* try again later */ 652 653 return; 654 } 655 656 /* flush the queue */ 657 ms->ms_eventstate = EVENT_WHEEL; 658 } 659 } 660 } 661 662 663 /* 664 * usbms_rserv_vuid_button() : 665 * Process a VUID button event 666 */ 667 static void 668 usbms_rserv_vuid_button(queue_t *q, 669 struct usbmouseinfo *mi, 670 mblk_t **bpaddr) 671 { 672 usbms_state_t *usbmsp = q->q_ptr; 673 struct ms_softc *ms; 674 int button_number; 675 uchar_t hwbit = 0x0; 676 Firm_event *fep; 677 mblk_t *bp; 678 uchar_t nbutt; 679 680 ms = &usbmsp->usbms_softc; 681 682 /* Test button. Send an event if it changed. */ 683 nbutt = (uchar_t)usbmsp->usbms_num_buttons; 684 button_number = nbutt - (EVENT_BUT(nbutt) - ms->ms_eventstate) - 1; 685 switch (button_number) { 686 case 2: 687 /* Right button */ 688 hwbit = 0x01; 689 690 break; 691 case 1: 692 /* Middle button */ 693 hwbit = 0x02; 694 695 break; 696 case 0: 697 /* Left button */ 698 hwbit = 0x04; 699 700 break; 701 default : 702 /* Any other button */ 703 hwbit = USBMS_BUT(nbutt) >> (EVENT_BUT(nbutt) - 704 ms->ms_eventstate); 705 706 break; 707 } 708 709 if ((ms->ms_prevbuttons & hwbit) != 710 (mi->mi_buttons & hwbit)) { 711 if ((bp = allocb(sizeof (Firm_event), 712 BPRI_HI)) != NULL) { 713 *bpaddr = bp; 714 fep = (Firm_event *)bp->b_wptr; 715 fep->id = vuid_id_addr( 716 ms->ms_vuidaddr) | 717 vuid_id_offset(BUT(1) 718 + button_number); 719 fep->pair_type = FE_PAIR_NONE; 720 fep->pair = 0; 721 722 /* 723 * Update read buttons and set 724 * value 725 */ 726 if (mi->mi_buttons & hwbit) { 727 fep->value = 0; 728 ms->ms_prevbuttons |= 729 hwbit; 730 } else { 731 fep->value = 1; 732 ms->ms_prevbuttons &= 733 ~hwbit; 734 } 735 fep->time = mi->mi_time; 736 } else { 737 if (usbmsp->usbms_resched_id) { 738 qunbufcall(q, 739 (bufcall_id_t)usbmsp->usbms_resched_id); 740 } 741 usbmsp->usbms_resched_id = 742 qbufcall(q, 743 sizeof (Firm_event), 744 BPRI_HI, 745 (void (*)())usbms_resched, 746 (void *) usbmsp); 747 if (usbmsp->usbms_resched_id == 0) 748 /* try again later */ 749 return; 750 /* 751 * bufcall failed; just pitch 752 * this event 753 */ 754 /* or maybe flush queue? */ 755 ms->ms_eventstate = EVENT_WHEEL; 756 } 757 } 758 } 759 760 /* 761 * usbms_rserv_vuid_event_y() : 762 * Process a VUID y-event 763 */ 764 static void 765 usbms_rserv_vuid_event_y(register queue_t *q, 766 register struct usbmouseinfo *mi, 767 mblk_t **bpaddr) 768 { 769 usbms_state_t *usbmsp = q->q_ptr; 770 register struct ms_softc *ms; 771 register Firm_event *fep; 772 mblk_t *bp; 773 774 ms = &usbmsp->usbms_softc; 775 776 /* 777 * The (max, 0) message and (0, max) message are always sent before 778 * the button click message is sent on the IBM Bladecenter. Stop 779 * their sending may prevent the coordinate from moving to the 780 * (max, max). 781 */ 782 if (!(((usbmsp->usbms_idf).yattr) & HID_MAIN_ITEM_RELATIVE)) { 783 if ((mi->mi_x == 0) && 784 (mi->mi_y == usbmsp->usbms_logical_Ymax)) { 785 786 return; 787 } 788 } 789 790 /* Send y if changed. */ 791 if (mi->mi_y != 0) { 792 if ((bp = allocb(sizeof (Firm_event), 793 BPRI_HI)) != NULL) { 794 *bpaddr = bp; 795 fep = (Firm_event *)bp->b_wptr; 796 if (((usbmsp->usbms_idf).yattr) & 797 HID_MAIN_ITEM_RELATIVE) { 798 fep->id = vuid_id_addr( 799 ms->ms_vuidaddr) | 800 vuid_id_offset( 801 LOC_Y_DELTA); 802 fep->pair_type = 803 FE_PAIR_ABSOLUTE; 804 fep->pair = 805 (uchar_t)LOC_Y_ABSOLUTE; 806 fep->value = -(mi->mi_y); 807 } else { 808 fep->id = vuid_id_addr( 809 ms->ms_vuidaddr) | 810 vuid_id_offset( 811 LOC_Y_ABSOLUTE); 812 fep->pair_type = FE_PAIR_DELTA; 813 fep->pair = (uchar_t)LOC_Y_DELTA; 814 fep->value = (mi->mi_y * 815 ((usbmsp->usbms_resolution).height) / 816 usbmsp->usbms_logical_Ymax); 817 if ((mi->mi_y * 818 ((usbmsp->usbms_resolution).height) % 819 usbmsp->usbms_logical_Ymax) >= 820 (usbmsp->usbms_logical_Ymax / 2)) { 821 fep->value ++; 822 } 823 } 824 fep->time = mi->mi_time; 825 } else { 826 if (usbmsp->usbms_resched_id) { 827 qunbufcall(q, 828 (bufcall_id_t)usbmsp->usbms_resched_id); 829 } 830 usbmsp->usbms_resched_id = 831 qbufcall(q, 832 sizeof (Firm_event), 833 BPRI_HI, 834 (void (*)())usbms_resched, 835 (void *)usbmsp); 836 if (usbmsp->usbms_resched_id == 0) { 837 /* try again later */ 838 return; 839 } 840 841 /* 842 * bufcall failed; just pitch 843 * this event 844 */ 845 /* or maybe flush queue? */ 846 ms->ms_eventstate = EVENT_WHEEL; 847 } 848 } 849 } 850 851 /* 852 * usbms_rserv_vuid_event_x() : 853 * Process a VUID x-event 854 */ 855 static void 856 usbms_rserv_vuid_event_x(register queue_t *q, 857 register struct usbmouseinfo *mi, 858 mblk_t **bpaddr) 859 { 860 usbms_state_t *usbmsp = q->q_ptr; 861 register struct ms_softc *ms; 862 register Firm_event *fep; 863 mblk_t *bp; 864 865 ms = &usbmsp->usbms_softc; 866 867 /* 868 * The (max, 0) message and (0, max) message are always sent before 869 * the button click message is sent on the IBM Bladecenter. Stop 870 * their sending may prevent the coordinate from moving to the 871 * (max, max). 872 */ 873 if (!(((usbmsp->usbms_idf).xattr) & HID_MAIN_ITEM_RELATIVE)) { 874 if ((mi->mi_y == 0) && 875 (mi->mi_x == usbmsp->usbms_logical_Xmax)) { 876 877 return; 878 } 879 } 880 881 /* Send x if changed. */ 882 if (mi->mi_x != 0) { 883 if ((bp = allocb(sizeof (Firm_event), 884 BPRI_HI)) != NULL) { 885 *bpaddr = bp; 886 fep = (Firm_event *)bp->b_wptr; 887 if (((usbmsp->usbms_idf).xattr) & 888 HID_MAIN_ITEM_RELATIVE) { 889 fep->id = vuid_id_addr( 890 ms->ms_vuidaddr) | 891 vuid_id_offset(LOC_X_DELTA); 892 fep->pair_type = 893 FE_PAIR_ABSOLUTE; 894 fep->pair = 895 (uchar_t)LOC_X_ABSOLUTE; 896 fep->value = mi->mi_x; 897 } else { 898 fep->id = vuid_id_addr(ms->ms_vuidaddr) | 899 vuid_id_offset(LOC_X_ABSOLUTE); 900 fep->pair_type = FE_PAIR_DELTA; 901 fep->pair = (uchar_t)LOC_X_DELTA; 902 fep->value = (mi->mi_x * 903 ((usbmsp->usbms_resolution).width) / 904 usbmsp->usbms_logical_Xmax); 905 if ((mi->mi_x * 906 ((usbmsp->usbms_resolution).width) % 907 usbmsp->usbms_logical_Xmax) >= 908 (usbmsp->usbms_logical_Xmax / 2)) { 909 fep->value ++; 910 } 911 } 912 fep->time = mi->mi_time; 913 } else { 914 if (usbmsp->usbms_resched_id) 915 qunbufcall(q, 916 (bufcall_id_t)usbmsp->usbms_resched_id); 917 usbmsp->usbms_resched_id = 918 qbufcall(q, 919 sizeof (Firm_event), 920 BPRI_HI, 921 (void (*)())usbms_resched, 922 (void *) usbmsp); 923 if (usbmsp->usbms_resched_id == 0) 924 /* try again later */ 925 return; 926 927 /* 928 * bufcall failed; just 929 * pitch this event 930 */ 931 /* or maybe flush queue? */ 932 ms->ms_eventstate = EVENT_WHEEL; 933 } 934 } 935 } 936 937 /* 938 * usbms_resched() : 939 * Callback routine for the qbufcall() in case 940 * of allocb() failure. When buffer becomes 941 * available, this function is called and 942 * enables the queue. 943 */ 944 static void 945 usbms_resched(void * usbmsp) 946 { 947 register queue_t *q; 948 register usbms_state_t *tmp_usbmsp = (usbms_state_t *)usbmsp; 949 950 tmp_usbmsp->usbms_resched_id = 0; 951 if ((q = tmp_usbmsp->usbms_rq_ptr) != 0) 952 qenable(q); /* run the service procedure */ 953 } 954 955 /* 956 * usbms_wput() : 957 * wput() routine for the mouse module. 958 * Module below : hid, module above : consms 959 */ 960 static int 961 usbms_wput(queue_t *q, 962 mblk_t *mp) 963 { 964 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle, 965 "usbms_wput entering"); 966 switch (mp->b_datap->db_type) { 967 968 case M_FLUSH: /* Canonical flush handling */ 969 if (*mp->b_rptr & FLUSHW) { 970 flushq(q, FLUSHDATA); 971 } 972 973 if (*mp->b_rptr & FLUSHR) { 974 flushq(RD(q), FLUSHDATA); 975 } 976 977 putnext(q, mp); /* pass it down the line. */ 978 break; 979 980 case M_IOCTL: 981 usbms_ioctl(q, mp); 982 break; 983 984 case M_IOCDATA: 985 usbms_miocdata(q, mp); 986 987 break; 988 default: 989 putnext(q, mp); /* pass it down the line. */ 990 } 991 992 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle, 993 "usbms_wput exiting"); 994 995 return (0); 996 } 997 998 999 /* 1000 * usbms_ioctl() : 1001 * Process ioctls we recognize and own. Otherwise, NAK. 1002 */ 1003 static void 1004 usbms_ioctl(register queue_t *q, 1005 register mblk_t *mp) 1006 { 1007 usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr; 1008 register struct ms_softc *ms; 1009 register struct iocblk *iocp; 1010 Vuid_addr_probe *addr_probe; 1011 uint_t ioctlrespsize; 1012 int err = 0; 1013 mblk_t *datap; 1014 ushort_t transparent = 0; 1015 1016 USB_DPRINTF_L3(PRINT_MASK_IOCTL, usbms_log_handle, 1017 "usbms_ioctl entering"); 1018 1019 if (usbmsp == NULL) { 1020 miocnak(q, mp, 0, EINVAL); 1021 1022 return; 1023 } 1024 ms = &usbmsp->usbms_softc; 1025 1026 iocp = (struct iocblk *)mp->b_rptr; 1027 switch (iocp->ioc_cmd) { 1028 1029 case VUIDSFORMAT: 1030 err = miocpullup(mp, sizeof (int)); 1031 if (err != 0) 1032 break; 1033 1034 if (*(int *)mp->b_cont->b_rptr == ms->ms_readformat) { 1035 break; 1036 } 1037 ms->ms_readformat = *(int *)mp->b_cont->b_rptr; 1038 /* 1039 * Flush mouse buffer because the messages upstream of us 1040 * are in the old format. 1041 */ 1042 1043 usbms_flush(usbmsp); 1044 break; 1045 1046 case VUIDGFORMAT: 1047 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 1048 ioctlrespsize = sizeof (int); 1049 goto allocfailure; 1050 } 1051 *(int *)datap->b_wptr = ms->ms_readformat; 1052 datap->b_wptr += sizeof (int); 1053 freemsg(mp->b_cont); 1054 mp->b_cont = datap; 1055 iocp->ioc_count = sizeof (int); 1056 break; 1057 1058 case VUIDGADDR: 1059 case VUIDSADDR: 1060 err = miocpullup(mp, sizeof (Vuid_addr_probe)); 1061 if (err != 0) 1062 break; 1063 1064 addr_probe = (Vuid_addr_probe *)mp->b_cont->b_rptr; 1065 if (addr_probe->base != VKEY_FIRST) { 1066 err = ENODEV; 1067 break; 1068 } 1069 if (iocp->ioc_cmd == VUIDSADDR) 1070 ms->ms_vuidaddr = addr_probe->data.next; 1071 else 1072 addr_probe->data.current = ms->ms_vuidaddr; 1073 break; 1074 1075 case MSIOGETPARMS: 1076 if ((datap = allocb(sizeof (Ms_parms), BPRI_HI)) == NULL) { 1077 ioctlrespsize = sizeof (Ms_parms); 1078 goto allocfailure; 1079 } 1080 err = usbms_getparms((Ms_parms *)datap->b_wptr, usbmsp); 1081 datap->b_wptr += sizeof (Ms_parms); 1082 freemsg(mp->b_cont); 1083 mp->b_cont = datap; 1084 iocp->ioc_count = sizeof (Ms_parms); 1085 break; 1086 1087 case MSIOSETPARMS: 1088 err = miocpullup(mp, sizeof (Ms_parms)); 1089 if (err != 0) 1090 break; 1091 err = usbms_setparms((Ms_parms *)mp->b_cont->b_rptr, usbmsp); 1092 break; 1093 1094 case MSIOBUTTONS: 1095 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 1096 ioctlrespsize = sizeof (int); 1097 goto allocfailure; 1098 } 1099 *(int *)datap->b_wptr = (int)usbmsp->usbms_num_buttons; 1100 datap->b_wptr += sizeof (int); 1101 freemsg(mp->b_cont); 1102 mp->b_cont = datap; 1103 iocp->ioc_count = sizeof (int); 1104 1105 break; 1106 case VUIDGWHEELCOUNT: 1107 /* 1108 * New IOCTL support. Since it's explicitly mentioned that 1109 * you can't add more ioctls to stream head's hard coded 1110 * list, we have to do the transparent ioctl processing 1111 * which is heavy. 1112 */ 1113 1114 /* Currently support for only one wheel */ 1115 1116 if (iocp->ioc_count == TRANSPARENT) { 1117 transparent = 1; 1118 if (err = usbms_make_copyreq(mp, 0, 0, sizeof (int), 1119 0, M_COPYOUT)) { 1120 1121 break; 1122 } 1123 } 1124 if ((datap = allocb(sizeof (int), BPRI_HI)) == NULL) { 1125 ioctlrespsize = sizeof (int); 1126 1127 goto allocfailure; 1128 } 1129 *((int *)datap->b_wptr) = (usbmsp->usbms_num_wheels ? 1 : 0); 1130 datap->b_wptr += sizeof (int); 1131 if (mp->b_cont) { 1132 freemsg(mp->b_cont); 1133 mp->b_cont = NULL; 1134 } 1135 mp->b_cont = datap; 1136 if (transparent) { 1137 qreply(q, mp); 1138 1139 return; 1140 } 1141 1142 break; 1143 case VUIDGWHEELINFO: 1144 if (iocp->ioc_count == TRANSPARENT) { 1145 if (err = usbms_make_copyreq(mp, 1146 sizeof (usbms_iocstate_t), 1147 USBMS_GETSTRUCT, 1148 sizeof (wheel_info), 1149 0, 1150 M_COPYIN)) { 1151 1152 break; 1153 } 1154 /* 1155 * If there is no b_cont the earlier func. will fail. 1156 * Hence there is no need for an explicit check here. 1157 */ 1158 freemsg(mp->b_cont); 1159 mp->b_cont = (mblk_t *)NULL; 1160 qreply(q, mp); 1161 1162 return; 1163 } 1164 if (mp->b_cont == NULL || iocp->ioc_count != 1165 sizeof (wheel_info)) { 1166 err = EINVAL; 1167 break; 1168 } 1169 datap = mp->b_cont; 1170 err = usbms_service_wheel_info(q, datap); 1171 1172 break; 1173 case VUIDGWHEELSTATE: 1174 if (iocp->ioc_count == TRANSPARENT) { 1175 if (err = usbms_make_copyreq(mp, 1176 sizeof (usbms_iocstate_t), 1177 USBMS_GETSTRUCT, 1178 sizeof (wheel_state), 1179 0, 1180 M_COPYIN)) { 1181 1182 break; 1183 } 1184 freemsg(mp->b_cont); 1185 mp->b_cont = (mblk_t *)NULL; 1186 qreply(q, mp); 1187 1188 return; 1189 } 1190 if ((mp->b_cont == NULL) || 1191 (iocp->ioc_count != sizeof (wheel_state))) { 1192 err = EINVAL; 1193 1194 break; 1195 } 1196 datap = mp->b_cont; 1197 err = usbms_service_wheel_state(q, datap, VUIDGWHEELSTATE); 1198 1199 break; 1200 case VUIDSWHEELSTATE: 1201 if (iocp->ioc_count == TRANSPARENT) { 1202 if (err = usbms_make_copyreq(mp, 1203 sizeof (usbms_iocstate_t), 1204 USBMS_GETSTRUCT, 1205 sizeof (wheel_state), 1206 0, 1207 M_COPYIN)) { 1208 1209 break; 1210 } 1211 freemsg(mp->b_cont); 1212 mp->b_cont = (mblk_t *)NULL; 1213 qreply(q, mp); 1214 1215 return; 1216 } 1217 if (mp->b_cont == NULL) { 1218 err = EINVAL; 1219 1220 break; 1221 } 1222 datap = mp->b_cont; 1223 err = usbms_service_wheel_state(q, datap, VUIDSWHEELSTATE); 1224 1225 break; 1226 case MSIOSRESOLUTION: 1227 if (iocp->ioc_count == TRANSPARENT) { 1228 if (err = usbms_make_copyreq(mp, 1229 sizeof (usbms_iocstate_t), 1230 USBMS_GETSTRUCT, 1231 sizeof (Ms_screen_resolution), 1232 0, 1233 M_COPYIN)) { 1234 1235 break; 1236 } 1237 1238 freemsg(mp->b_cont); 1239 mp->b_cont = (mblk_t *)NULL; 1240 qreply(q, mp); 1241 1242 return; 1243 } 1244 if (mp->b_cont == NULL) { 1245 err = EINVAL; 1246 1247 break; 1248 } 1249 datap = mp->b_cont; 1250 err = usbms_get_screen_parms(q, datap); 1251 break; 1252 1253 default: 1254 putnext(q, mp); /* pass it down the line */ 1255 1256 return; 1257 } /* switch */ 1258 1259 if (err != 0) 1260 miocnak(q, mp, 0, err); 1261 else { 1262 iocp->ioc_rval = 0; 1263 iocp->ioc_error = 0; 1264 mp->b_datap->db_type = M_IOCACK; 1265 qreply(q, mp); 1266 } 1267 1268 return; 1269 1270 allocfailure: 1271 /* 1272 * We needed to allocate something to handle this "ioctl", but 1273 * couldn't; save this "ioctl" and arrange to get called back when 1274 * it's more likely that we can get what we need. 1275 * If there's already one being saved, throw it out, since it 1276 * must have timed out. 1277 */ 1278 freemsg(usbmsp->usbms_iocpending); 1279 usbmsp->usbms_iocpending = mp; 1280 if (usbmsp->usbms_reioctl_id) { 1281 qunbufcall(q, (bufcall_id_t)usbmsp->usbms_reioctl_id); 1282 } 1283 usbmsp->usbms_reioctl_id = qbufcall(q, ioctlrespsize, BPRI_HI, 1284 (void (*)())usbms_reioctl, 1285 (void *)usbmsp); 1286 } 1287 1288 1289 /* 1290 * M_IOCDATA processing for IOCTL's: VUIDGWHEELCOUNT, VUIDGWHEELINFO, 1291 * VUIDGWHEELSTATE, VUIDSWHEELSTATE & MSIOSRESOLUTION. 1292 */ 1293 static void 1294 usbms_miocdata(register queue_t *q, 1295 register mblk_t *mp) 1296 { 1297 struct copyresp *copyresp; 1298 struct iocblk *iocbp; 1299 mblk_t *datap; 1300 mblk_t *ioctmp; 1301 usbms_iocstate_t *usbmsioc; 1302 int err = 0; 1303 1304 copyresp = (struct copyresp *)mp->b_rptr; 1305 iocbp = (struct iocblk *)mp->b_rptr; 1306 if (copyresp->cp_rval) { 1307 err = EAGAIN; 1308 1309 goto err; 1310 } 1311 switch (copyresp->cp_cmd) { 1312 1313 case VUIDGWHEELCOUNT: 1314 usbms_ack_ioctl(mp); 1315 1316 break; 1317 case VUIDGWHEELINFO: 1318 ioctmp = copyresp->cp_private; 1319 usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr; 1320 if (usbmsioc->ioc_state == USBMS_GETSTRUCT) { 1321 if (mp->b_cont == NULL) { 1322 err = EINVAL; 1323 1324 break; 1325 } 1326 datap = (mblk_t *)mp->b_cont; 1327 if (err = usbms_service_wheel_info(q, datap)) { 1328 1329 goto err; 1330 } 1331 if (err = usbms_make_copyreq(mp, 0, USBMS_GETRESULT, 1332 sizeof (wheel_info), 0, M_COPYOUT)) { 1333 1334 goto err; 1335 } 1336 } else if (usbmsioc->ioc_state == USBMS_GETRESULT) { 1337 freemsg(ioctmp); 1338 usbms_ack_ioctl(mp); 1339 } 1340 1341 break; 1342 case VUIDGWHEELSTATE: 1343 ioctmp = (mblk_t *)copyresp->cp_private; 1344 usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr; 1345 if (usbmsioc->ioc_state == USBMS_GETSTRUCT) { 1346 if (mp->b_cont == NULL) { 1347 err = EINVAL; 1348 1349 break; 1350 } 1351 if (err = usbms_service_wheel_state(q, mp->b_cont, 1352 VUIDGWHEELSTATE)) { 1353 goto err; 1354 } 1355 if (err = usbms_make_copyreq(mp, 0, USBMS_GETRESULT, 1356 sizeof (wheel_state), 0, M_COPYOUT)) { 1357 1358 goto err; 1359 } 1360 } else if (usbmsioc->ioc_state == USBMS_GETRESULT) { 1361 freemsg(ioctmp); 1362 usbms_ack_ioctl(mp); 1363 } 1364 1365 break; 1366 case VUIDSWHEELSTATE: 1367 ioctmp = (mblk_t *)copyresp->cp_private; 1368 usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr; 1369 if (mp->b_cont == NULL) { 1370 err = EINVAL; 1371 1372 break; 1373 } 1374 if (err = usbms_service_wheel_state(q, mp->b_cont, 1375 VUIDSWHEELSTATE)) { 1376 1377 goto err; 1378 } 1379 freemsg(ioctmp); 1380 usbms_ack_ioctl(mp); 1381 1382 break; 1383 case MSIOSRESOLUTION: 1384 ioctmp = (mblk_t *)copyresp->cp_private; 1385 usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr; 1386 if (mp->b_cont == NULL) { 1387 err = EINVAL; 1388 1389 break; 1390 } 1391 if (err = usbms_get_screen_parms(q, mp->b_cont)) { 1392 1393 goto err; 1394 } 1395 freemsg(ioctmp); 1396 usbms_ack_ioctl(mp); 1397 1398 break; 1399 default: 1400 err = EINVAL; 1401 break; 1402 } 1403 1404 err: 1405 if (err) { 1406 mp->b_datap->db_type = M_IOCNAK; 1407 if (mp->b_cont) { 1408 freemsg(mp->b_cont); 1409 mp->b_cont = (mblk_t *)NULL; 1410 } 1411 if (copyresp->cp_private) { 1412 freemsg((mblk_t *)copyresp->cp_private); 1413 copyresp->cp_private = (mblk_t *)NULL; 1414 } 1415 iocbp->ioc_count = 0; 1416 iocbp->ioc_error = err; 1417 } 1418 qreply(q, mp); 1419 } 1420 1421 1422 /* 1423 * usbms_reioctl() : 1424 * This function is set up as call-back function should an ioctl fail. 1425 * It retries the ioctl. 1426 */ 1427 static void 1428 usbms_reioctl(void * usbms_addr) 1429 { 1430 usbms_state_t *usbmsp = (usbms_state_t *)usbms_addr; 1431 register queue_t *q; 1432 register mblk_t *mp; 1433 1434 q = usbmsp->usbms_wq_ptr; 1435 if ((mp = usbmsp->usbms_iocpending) != NULL) { 1436 usbmsp->usbms_iocpending = NULL; /* not pending any more */ 1437 usbms_ioctl(q, mp); 1438 } 1439 } 1440 1441 /* 1442 * usbms_getparms() : 1443 * Called from MSIOGETPARMS ioctl to get the 1444 * current jitter_thesh, speed_law and speed_limit 1445 * values. 1446 */ 1447 static int 1448 usbms_getparms(register Ms_parms *data, 1449 usbms_state_t *usbmsp) 1450 { 1451 data->jitter_thresh = usbmsp->usbms_jitter_thresh; 1452 data->speed_law = usbmsp->usbms_speedlaw; 1453 data->speed_limit = usbmsp->usbms_speedlimit; 1454 1455 return (0); 1456 } 1457 1458 1459 /* 1460 * usbms_setparms() : 1461 * Called from MSIOSETPARMS ioctl to set the 1462 * current jitter_thesh, speed_law and speed_limit 1463 * values. 1464 */ 1465 static int 1466 usbms_setparms(register Ms_parms *data, 1467 usbms_state_t *usbmsp) 1468 { 1469 usbmsp->usbms_jitter_thresh = data->jitter_thresh; 1470 usbmsp->usbms_speedlaw = data->speed_law; 1471 usbmsp->usbms_speedlimit = data->speed_limit; 1472 1473 return (0); 1474 } 1475 1476 /* 1477 * usbms_flush() : 1478 * Resets the ms_softc structure to default values 1479 * and sends M_FLUSH above. 1480 */ 1481 static void 1482 usbms_flush(usbms_state_t *usbmsp) 1483 { 1484 register struct ms_softc *ms = &usbmsp->usbms_softc; 1485 register queue_t *q; 1486 1487 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle, 1488 "usbms_flush entering"); 1489 1490 ms->ms_oldoff = 0; 1491 ms->ms_eventstate = EVENT_BUT(usbmsp->usbms_num_buttons); 1492 usbmsp->usbms_buf->mb_off = 0; 1493 ms->ms_prevbuttons = (char)USB_NO_BUT_PRESSED; 1494 usbmsp->usbms_oldbutt = ms->ms_prevbuttons; 1495 if ((q = usbmsp->usbms_rq_ptr) != NULL && q->q_next != NULL) { 1496 (void) putnextctl1(q, M_FLUSH, FLUSHR); 1497 } 1498 1499 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle, 1500 "usbms_flush exiting"); 1501 } 1502 1503 1504 /* 1505 * usbms_rput() : 1506 * Put procedure for input from driver end of stream (read queue). 1507 */ 1508 static void 1509 usbms_rput(queue_t *q, 1510 mblk_t *mp) 1511 { 1512 usbms_state_t *usbmsp = q->q_ptr; 1513 mblk_t *tmp_mp; 1514 ushort_t limit = (usbmsp->usbms_idf).tlen; 1515 1516 /* Maintain the original mp */ 1517 tmp_mp = mp; 1518 1519 if (usbmsp == 0) { 1520 freemsg(mp); /* nobody's listening */ 1521 1522 return; 1523 } 1524 1525 switch (mp->b_datap->db_type) { 1526 1527 case M_FLUSH: 1528 if (*mp->b_rptr & FLUSHW) 1529 flushq(WR(q), FLUSHDATA); 1530 if (*mp->b_rptr & FLUSHR) 1531 flushq(q, FLUSHDATA); 1532 freemsg(mp); 1533 1534 return; 1535 1536 case M_BREAK: 1537 /* 1538 * We don't have to handle this 1539 * because nothing is sent from the downstream 1540 */ 1541 1542 freemsg(mp); 1543 1544 return; 1545 1546 case M_DATA: 1547 if (!(usbmsp->usbms_flags & USBMS_OPEN)) { 1548 freemsg(mp); /* not ready to listen */ 1549 1550 return; 1551 } 1552 break; 1553 1554 case M_CTL: 1555 usbms_mctl_receive(q, mp); 1556 1557 return; 1558 1559 case M_ERROR: 1560 usbmsp->usbms_protoerr = 1; 1561 usbmsp->usbms_flags &= ~USBMS_QWAIT; 1562 freemsg(mp); 1563 1564 return; 1565 default: 1566 putnext(q, mp); 1567 1568 return; 1569 } 1570 1571 /* 1572 * A data message, consisting of bytes from the mouse. 1573 * Make sure there are atleast "limit" number of bytes. 1574 */ 1575 if (((tmp_mp->b_wptr - tmp_mp->b_rptr) < limit) || 1576 (((tmp_mp->b_wptr - tmp_mp->b_rptr) == limit) && 1577 (usbmsp->usbms_rptid != HID_REPORT_ID_UNDEFINED))) { 1578 freemsg(mp); 1579 return; 1580 } 1581 do { 1582 if (usbmsp->usbms_rptid != HID_REPORT_ID_UNDEFINED) { 1583 if (*(tmp_mp->b_rptr) != usbmsp->usbms_rptid) { 1584 freemsg(mp); 1585 1586 return; 1587 } else { 1588 /* We skip the report id prefix. */ 1589 tmp_mp->b_rptr++; 1590 } 1591 } 1592 1593 usbms_input(usbmsp, tmp_mp); 1594 } while ((tmp_mp = tmp_mp->b_cont) != NULL); /* next block, if any */ 1595 1596 freemsg(mp); 1597 } 1598 1599 1600 /* 1601 * usbms_mctl_receive() : 1602 * Handle M_CTL messages from hid. If 1603 * we don't understand the command, free message. 1604 */ 1605 static void 1606 usbms_mctl_receive(register queue_t *q, 1607 register mblk_t *mp) 1608 { 1609 usbms_state_t *usbmsd = (usbms_state_t *)q->q_ptr; 1610 struct iocblk *iocp; 1611 caddr_t data; 1612 1613 1614 iocp = (struct iocblk *)mp->b_rptr; 1615 if (mp->b_cont != NULL) 1616 data = (caddr_t)mp->b_cont->b_rptr; 1617 1618 switch (iocp->ioc_cmd) { 1619 1620 case HID_GET_PARSER_HANDLE: 1621 if ((data != NULL) && 1622 (iocp->ioc_count == sizeof (hidparser_handle_t)) && 1623 ((mp->b_cont->b_wptr - mp->b_cont->b_rptr) == 1624 iocp->ioc_count)) { 1625 usbmsd->usbms_report_descr_handle = 1626 *(hidparser_handle_t *)data; 1627 } else { 1628 usbmsd->usbms_report_descr_handle = NULL; 1629 } 1630 freemsg(mp); 1631 usbmsd->usbms_flags &= ~USBMS_QWAIT; 1632 break; 1633 case HID_SET_PROTOCOL: 1634 usbmsd->usbms_flags &= ~USBMS_QWAIT; 1635 1636 /* FALLTHRU */ 1637 default: 1638 freemsg(mp); 1639 break; 1640 } 1641 } 1642 1643 1644 /* 1645 * usbms_input() : 1646 * 1647 * Mouse input routine; process a byte received from a mouse and 1648 * assemble into a mouseinfo message for the window system. 1649 * 1650 * The USB mouse send a three-byte packet organized as 1651 * button, dx, dy 1652 * where dx and dy can be any signed byte value. The mouseinfo message 1653 * is organized as 1654 * dx, dy, button, timestamp 1655 * Our strategy is to collect but, dx & dy three-byte packet, then 1656 * send the mouseinfo message up. 1657 * 1658 * Basic algorithm: throw away bytes until we get a [potential] 1659 * button byte. Collect button; Collect dx; Collect dy; Send button, 1660 * dx, dy, timestamp. 1661 * 1662 * Watch out for overflow! 1663 * 1664 * cxyz, sxyz and ixyz stand for different length value in sample data. 1665 */ 1666 static void 1667 usbms_input(usbms_state_t *usbmsp, 1668 mblk_t *mp) 1669 { 1670 register struct usbmousebuf *b; 1671 register struct usbmouseinfo *mi; 1672 register int jitter_radius; 1673 register int temp = 0; 1674 register int32_t nbutt; 1675 ushort_t i; 1676 char c; 1677 char cxyz = 0; /* for one byte */ 1678 short sxyz = 0; /* for two bytes */ 1679 int ixyz = 0; /* for four bytes */ 1680 1681 1682 nbutt = usbmsp->usbms_num_buttons; 1683 b = usbmsp->usbms_buf; 1684 1685 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle, 1686 "usbms_input entering"); 1687 1688 if (b == NULL) { 1689 1690 return; 1691 } 1692 1693 mi = &b->mb_info[b->mb_off]; 1694 1695 /* 1696 * Lower 3 bits are middle, right, left. 1697 */ 1698 c = mp->b_rptr[(usbmsp->usbms_idf).bpos]; 1699 mi->mi_buttons = (char)USB_NO_BUT_PRESSED; 1700 if (c & USBMS_BUT(1)) { /* left button is pressed */ 1701 mi->mi_buttons = mi->mi_buttons & USB_LEFT_BUT_PRESSED; 1702 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, 1703 usbms_log_handle, 1704 "left button pressed"); 1705 } 1706 if (c & USBMS_BUT(2)) { /* right button is pressed */ 1707 mi->mi_buttons = mi->mi_buttons & USB_RIGHT_BUT_PRESSED; 1708 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, 1709 usbms_log_handle, 1710 "right button pressed"); 1711 } 1712 if (c & USBMS_BUT(3)) { /* middle button is pressed */ 1713 mi->mi_buttons = mi->mi_buttons & 1714 USB_MIDDLE_BUT_PRESSED; 1715 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, 1716 usbms_log_handle, 1717 "middle button pressed"); 1718 } 1719 1720 if (nbutt > 3) { 1721 for (i = 4; i < (nbutt + 1); i++) { 1722 if (c & USBMS_BUT(i)) { 1723 mi->mi_buttons = mi->mi_buttons & 1724 USB_BUT_PRESSED(i); 1725 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, 1726 usbms_log_handle, 1727 "%d button pressed", i); 1728 } 1729 } 1730 } 1731 1732 /* 1733 * According to the length of the X coordinate, 1734 * the current delta X is got from the sample. 1735 */ 1736 switch ((usbmsp->usbms_idf).xlen) { 1737 1738 case 1: 1739 1740 cxyz = mp->b_rptr[((usbmsp->usbms_idf).xpos)]; 1741 temp = (int)(mi->mi_x + cxyz); 1742 1743 break; 1744 case 2: 1745 1746 for (i = 0; i < 2; i++) { 1747 sxyz = sxyz | (mp->b_rptr[((usbmsp->usbms_idf).xpos) 1748 + i] << (8 * i)); 1749 } 1750 temp = (int)(mi->mi_x + sxyz); 1751 1752 break; 1753 1754 case 4: 1755 for (i = 0; i < 4; i++) { 1756 ixyz = ixyz | (mp->b_rptr[((usbmsp->usbms_idf).xpos) 1757 + i] << (8 * i)); 1758 } 1759 temp = (int)(mi->mi_x + ixyz); 1760 1761 break; 1762 1763 } 1764 1765 if (((usbmsp->usbms_idf).xlen) == 1) { 1766 mi->mi_x = USB_BYTECLIP(temp); 1767 } else { 1768 mi->mi_x = temp; 1769 } 1770 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, 1771 usbms_log_handle, "x = %d", (int)mi->mi_x); 1772 1773 uniqtime32(&mi->mi_time); /* record time when sample arrived */ 1774 1775 /* 1776 * According to the length of the Y coordinate, 1777 * the current delta Y is got from the sample. 1778 */ 1779 cxyz = sxyz = ixyz = 0; 1780 switch ((usbmsp->usbms_idf).ylen) { 1781 1782 case 1: 1783 1784 cxyz = mp->b_rptr[((usbmsp->usbms_idf).ypos)]; 1785 temp = (int)(mi->mi_y + cxyz); 1786 1787 break; 1788 case 2: 1789 1790 for (i = 0; i < 2; i++) { 1791 sxyz = sxyz | (mp->b_rptr[((usbmsp->usbms_idf).ypos) 1792 + i] << (8 * i)); 1793 } 1794 temp = (int)(mi->mi_y + sxyz); 1795 1796 break; 1797 1798 case 4: 1799 for (i = 0; i < 4; i++) { 1800 ixyz = ixyz | (mp->b_rptr[((usbmsp->usbms_idf).ypos) 1801 + i] << (8 * i)); 1802 } 1803 temp = (int)(mi->mi_y + ixyz); 1804 1805 break; 1806 1807 } 1808 if (((usbmsp->usbms_idf).ylen) == 1) { 1809 mi->mi_y = USB_BYTECLIP(temp); 1810 } else { 1811 mi->mi_y = temp; 1812 } 1813 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle, 1814 "y = %d", (int)mi->mi_y); 1815 1816 /* 1817 * Check the wheel data in the current event. 1818 * If it exists, the wheel data is got from the sample. 1819 */ 1820 1821 if (usbmsp->usbms_num_wheels) { 1822 cxyz = sxyz = ixyz = temp = 0; 1823 switch ((usbmsp->usbms_idf).zlen) { 1824 1825 case 1: 1826 1827 cxyz = mp->b_rptr[((usbmsp->usbms_idf).zpos)]; 1828 temp = (int)(mi->mi_z + cxyz); 1829 1830 break; 1831 case 2: 1832 1833 for (i = 0; i < 2; i++) { 1834 sxyz = sxyz | 1835 (mp->b_rptr[((usbmsp->usbms_idf).zpos) 1836 + i] << (8 * i)); 1837 } 1838 temp = (int)(mi->mi_z + sxyz); 1839 1840 break; 1841 1842 case 4: 1843 for (i = 0; i < 4; i++) { 1844 ixyz = ixyz | 1845 (mp->b_rptr[((usbmsp->usbms_idf).zpos) 1846 + i] << (8 * i)); 1847 } 1848 temp = (int)(mi->mi_z + ixyz); 1849 1850 break; 1851 } 1852 1853 if (((usbmsp->usbms_idf).zlen) == 1) { 1854 mi->mi_z = USB_BYTECLIP(temp); 1855 } else { 1856 mi->mi_z = temp; 1857 } 1858 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle, 1859 "z = %d", (int)mi->mi_z); 1860 } 1861 1862 if (usbmsp->usbms_jitter) { 1863 (void) quntimeout(usbmsp->usbms_rq_ptr, 1864 (timeout_id_t)usbmsp->usbms_timeout_id); 1865 usbmsp->usbms_jitter = 0; 1866 } 1867 1868 if (!usbmsp->usbms_num_wheels) { 1869 mi->mi_z = 0; 1870 } 1871 1872 /* 1873 * If there is a wheel movement or a change in the button state, 1874 * send the data up immediately. 1875 */ 1876 if (!(mi->mi_z) && (mi->mi_buttons == usbmsp->usbms_oldbutt)) { 1877 /* 1878 * Buttons did not change; did position? 1879 */ 1880 if (mi->mi_x == 0 && mi->mi_y == 0) { 1881 /* no, position did not change */ 1882 1883 return; 1884 } 1885 1886 /* 1887 * Did the mouse move more than the jitter threshhold? 1888 */ 1889 jitter_radius = usbmsp->usbms_jitter_thresh; 1890 if (USB_ABS((int)mi->mi_x) <= jitter_radius && 1891 USB_ABS((int)mi->mi_y) <= jitter_radius) { 1892 /* 1893 * Mouse moved less than the jitter threshhold. 1894 * Don't indicate an event; keep accumulating motions. 1895 * After "jittertimeout" ticks expire, treat 1896 * the accumulated delta as the real delta. 1897 */ 1898 usbmsp->usbms_jitter = 1; 1899 usbmsp->usbms_timeout_id = 1900 qtimeout(usbmsp->usbms_rq_ptr, (void (*)())usbms_incr, 1901 (void *)usbmsp, (clock_t)usbmsp->usbms_jittertimeout); 1902 1903 return; 1904 } 1905 } 1906 usbmsp->usbms_oldbutt = mi->mi_buttons; 1907 usbms_incr(usbmsp); 1908 1909 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle, 1910 "usbms_input exiting"); 1911 } 1912 1913 1914 /* 1915 * usbms_incr() : 1916 * Increment the mouse sample pointer. 1917 * Called either immediately after a sample or after a jitter timeout. 1918 */ 1919 static void 1920 usbms_incr(void *arg) 1921 { 1922 usbms_state_t *usbmsp = arg; 1923 register struct ms_softc *ms = &usbmsp->usbms_softc; 1924 register struct usbmousebuf *b; 1925 register struct usbmouseinfo *mi; 1926 register int xc, yc, zc; 1927 register int wake; 1928 register int speedl = usbmsp->usbms_speedlimit; 1929 register int xabs, yabs; 1930 1931 /* 1932 * No longer waiting for jitter timeout 1933 */ 1934 usbmsp->usbms_jitter = 0; 1935 1936 b = usbmsp->usbms_buf; 1937 1938 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle, 1939 "usbms_incr entering"); 1940 1941 if (b == NULL) { 1942 1943 return; 1944 } 1945 mi = &b->mb_info[b->mb_off]; 1946 if (usbmsp->usbms_speedlaw) { 1947 xabs = USB_ABS((int)mi->mi_x); 1948 yabs = USB_ABS((int)mi->mi_y); 1949 if (xabs > speedl || yabs > speedl) { 1950 usbmsp->usbms_speed_count++; 1951 } 1952 if (xabs > speedl) { 1953 mi->mi_x = 0; 1954 } 1955 if (yabs > speedl) { 1956 mi->mi_y = 0; 1957 } 1958 } 1959 1960 1961 xc = yc = zc = 0; 1962 1963 /* See if we need to wake up anyone waiting for input */ 1964 wake = b->mb_off == ms->ms_oldoff; 1965 1966 /* Adjust circular buffer pointer */ 1967 if (++b->mb_off >= b->mb_size) { 1968 b->mb_off = 0; 1969 mi = b->mb_info; 1970 } else { 1971 mi++; 1972 } 1973 1974 /* 1975 * If over-took read index then flush buffer so that mouse state 1976 * is consistent. 1977 */ 1978 if (b->mb_off == ms->ms_oldoff) { 1979 if (overrun_msg) { 1980 USB_DPRINTF_L1(PRINT_MASK_ALL, usbms_log_handle, 1981 "Mouse buffer flushed when overrun."); 1982 } 1983 usbms_flush(usbmsp); 1984 overrun_cnt++; 1985 mi = b->mb_info; 1986 } 1987 1988 /* Remember current buttons and fractional part of x & y */ 1989 mi->mi_buttons = (char)USB_NO_BUT_PRESSED; 1990 mi->mi_x = xc; 1991 mi->mi_y = yc; 1992 mi->mi_z = zc; 1993 1994 if (wake) { 1995 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle, 1996 "usbms_incr run service"); 1997 qenable(usbmsp->usbms_rq_ptr); /* run the service proc */ 1998 } 1999 USB_DPRINTF_L3(PRINT_MASK_INPUT_INCR, usbms_log_handle, 2000 "usbms_incr exiting"); 2001 } 2002 2003 2004 /* 2005 * usbms_check_for_wheels 2006 * return SUCCESS if wheel is found, else return FAILURE 2007 */ 2008 static int 2009 usbms_check_for_wheels(usbms_state_t *usbmsp) 2010 { 2011 int rval, report_id; 2012 2013 2014 if (usbmsp->usbms_report_descr_handle) { 2015 /* Get the report id that has mouse data */ 2016 if (hidparser_get_usage_attribute( 2017 usbmsp->usbms_report_descr_handle, 2018 0, /* Doesn't matter */ 2019 HIDPARSER_ITEM_INPUT, 2020 HID_GENERIC_DESKTOP, 2021 HID_GD_X, 2022 HIDPARSER_ITEM_REPORT_ID, 2023 &usbmsp->usbms_rptid) == HIDPARSER_NOT_FOUND) { 2024 usbmsp->usbms_rptid = HID_REPORT_ID_UNDEFINED; 2025 report_id = 0; 2026 } else { 2027 report_id = usbmsp->usbms_rptid; 2028 } 2029 2030 /* find no. of wheels in this report */ 2031 rval = hidparser_get_usage_attribute( 2032 usbmsp->usbms_report_descr_handle, 2033 report_id, 2034 HIDPARSER_ITEM_INPUT, 2035 HID_GENERIC_DESKTOP, 2036 HID_GD_WHEEL, 2037 HIDPARSER_ITEM_REPORT_COUNT, 2038 &usbmsp->usbms_num_wheels); 2039 if (rval == HIDPARSER_SUCCESS) { 2040 /* 2041 * Found wheel. By default enable the wheel. 2042 * Currently only enable only the first wheel. 2043 */ 2044 usbmsp->usbms_wheel_state_bf |= 2045 VUID_WHEEL_STATE_ENABLED; 2046 2047 return (USB_SUCCESS); 2048 } 2049 } 2050 usbmsp->usbms_num_wheels = 0; 2051 2052 return (USB_FAILURE); 2053 } 2054 2055 2056 /* 2057 * usbms_make_copyreq 2058 * helper function for usbms ioctls 2059 */ 2060 static int 2061 usbms_make_copyreq(mblk_t *mp, 2062 uint_t pvtsize, 2063 uint_t state, 2064 uint_t reqsize, 2065 uint_t contsize, 2066 uint_t copytype) 2067 { 2068 2069 struct copyreq *cq; 2070 struct copyresp *cr; 2071 mblk_t *ioctmp; 2072 mblk_t *conttmp; 2073 usbms_iocstate_t *usbmsioc; 2074 2075 if ((!pvtsize) && state) { 2076 cr = (struct copyresp *)mp->b_rptr; 2077 ioctmp = cr->cp_private; 2078 } 2079 cq = (struct copyreq *)mp->b_rptr; 2080 if (mp->b_cont == NULL) { 2081 2082 return (EINVAL); 2083 } 2084 cq->cq_addr = *((caddr_t *)mp->b_cont->b_rptr); 2085 cq->cq_size = reqsize; 2086 cq->cq_flag = 0; 2087 if (pvtsize) { 2088 ioctmp = (mblk_t *)allocb(pvtsize, BPRI_MED); 2089 if (ioctmp == NULL) { 2090 2091 return (EAGAIN); 2092 } 2093 cq->cq_private = ioctmp; 2094 ioctmp = cq->cq_private; 2095 } 2096 if (state) { 2097 usbmsioc = (usbms_iocstate_t *)ioctmp->b_rptr; 2098 usbmsioc->ioc_state = state; 2099 if (pvtsize) { 2100 usbmsioc->u_addr = cq->cq_addr; 2101 } else { 2102 cq->cq_addr = usbmsioc->u_addr; 2103 cq->cq_private = ioctmp; 2104 } 2105 ioctmp->b_wptr = ioctmp->b_rptr + sizeof (usbms_iocstate_t); 2106 } 2107 if (contsize) { 2108 conttmp = (mblk_t *)allocb(contsize, BPRI_MED); 2109 if (conttmp == NULL) { 2110 2111 return (EAGAIN); 2112 } 2113 if (mp->b_cont) { 2114 freemsg(mp->b_cont); 2115 mp->b_cont = conttmp; 2116 } 2117 } 2118 mp->b_datap->db_type = copytype; 2119 mp->b_wptr = mp->b_rptr + sizeof (struct copyreq); 2120 2121 return (USB_SUCCESS); 2122 } 2123 2124 2125 static int 2126 usbms_service_wheel_info(register queue_t *q, register mblk_t *datap) 2127 { 2128 2129 wheel_info *wi; 2130 usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr; 2131 uint_t err; 2132 2133 wi = (wheel_info *)datap->b_rptr; 2134 if (wi->vers != VUID_WHEEL_INFO_VERS) { 2135 err = EINVAL; 2136 2137 return (err); 2138 } 2139 if (wi->id > (usbmsp->usbms_num_wheels - 1)) { 2140 err = EINVAL; 2141 2142 return (err); 2143 } 2144 wi->format = (usbmsp->usbms_wheel_orient_bf & (1 << wi->id)) ? 2145 VUID_WHEEL_FORMAT_HORIZONTAL : VUID_WHEEL_FORMAT_VERTICAL; 2146 2147 return (USB_SUCCESS); 2148 } 2149 2150 2151 static int 2152 usbms_service_wheel_state(register queue_t *q, 2153 register mblk_t *datap, 2154 register uint_t cmd) 2155 { 2156 2157 wheel_state *ws; 2158 uint_t err; 2159 usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr; 2160 2161 ws = (wheel_state *)datap->b_rptr; 2162 if (ws->vers != VUID_WHEEL_STATE_VERS) { 2163 err = EINVAL; 2164 2165 return (err); 2166 } 2167 if (ws->id > (usbmsp->usbms_num_wheels - 1)) { 2168 err = EINVAL; 2169 2170 return (err); 2171 } 2172 2173 switch (cmd) { 2174 case VUIDGWHEELSTATE: 2175 ws->stateflags = (usbmsp->usbms_wheel_state_bf >> ws->id) & 2176 VUID_WHEEL_STATE_ENABLED; 2177 2178 break; 2179 case VUIDSWHEELSTATE: 2180 usbmsp->usbms_wheel_state_bf = (ws->stateflags << ws->id) | 2181 (~(1 << ws->id) & usbmsp->usbms_wheel_state_bf); 2182 2183 break; 2184 default: 2185 err = EINVAL; 2186 2187 return (err); 2188 } 2189 2190 return (USB_SUCCESS); 2191 } 2192 2193 2194 /* 2195 * usbms_get_screen_parms() : 2196 * Called from MSIOSRESOLUTION ioctl to get the 2197 * current screen height/width params from X. 2198 */ 2199 static int 2200 usbms_get_screen_parms(register queue_t *q, 2201 register mblk_t *datap) 2202 { 2203 2204 usbms_state_t *usbmsp = (usbms_state_t *)q->q_ptr; 2205 Ms_screen_resolution *res = &(usbmsp->usbms_resolution); 2206 Ms_screen_resolution *data; 2207 2208 data = (Ms_screen_resolution *)datap->b_rptr; 2209 res->height = data->height; 2210 res->width = data->width; 2211 2212 return (USB_SUCCESS); 2213 } 2214 2215 2216 static void 2217 usbms_ack_ioctl(mblk_t *mp) 2218 { 2219 2220 struct iocblk *iocbp = (struct iocblk *)mp->b_rptr; 2221 2222 mp->b_datap->db_type = M_IOCACK; 2223 mp->b_wptr = mp->b_rptr + sizeof (struct iocblk); 2224 iocbp->ioc_error = 0; 2225 iocbp->ioc_count = 0; 2226 iocbp->ioc_rval = 0; 2227 if (mp->b_cont != NULL) { 2228 freemsg(mp->b_cont); 2229 mp->b_cont = NULL; 2230 } 2231 } 2232 2233 2234 /* 2235 * usbms_read_input_data_format() : 2236 * Get the mouse packet length and usages' length. 2237 * Check whether X and Y are relative or absolute. 2238 * 2239 * If they are absolute, the X and Y logical max values 2240 * will be got. A firm event will be created and sent 2241 * to the upper level. 2242 */ 2243 int 2244 usbms_read_input_data_format(usbms_state_t *usbmsp) 2245 { 2246 2247 hidparser_rpt_t *ms_rpt; 2248 uint_t i, j, button_page; 2249 uint_t limit = 0; 2250 uint32_t rptcnt, rptsz; 2251 usbms_idf *idf = &(usbmsp->usbms_idf); 2252 Ms_screen_resolution *res = &(usbmsp->usbms_resolution); 2253 Firm_event *fep; 2254 mblk_t *mb; 2255 register queue_t *q; 2256 int rval; 2257 2258 /* allocate hidparser report structure */ 2259 ms_rpt = kmem_zalloc(sizeof (hidparser_rpt_t), KM_SLEEP); 2260 2261 /* 2262 * Check what is the total length of the mouse packet 2263 * and get the usages and their lengths in order 2264 */ 2265 2266 rval = hidparser_get_usage_list_in_order( 2267 usbmsp->usbms_report_descr_handle, 2268 usbmsp->usbms_rptid, 2269 HIDPARSER_ITEM_INPUT, 2270 ms_rpt); 2271 2272 if (rval != HIDPARSER_SUCCESS) { 2273 2274 kmem_free(ms_rpt, sizeof (hidparser_rpt_t)); 2275 return (USB_FAILURE); 2276 } 2277 2278 for (i = 0; i < ms_rpt->no_of_usages; i++) { 2279 rptcnt = ms_rpt->usage_descr[i].rptcnt; 2280 rptsz = ms_rpt->usage_descr[i].rptsz; 2281 if (rptcnt == 0) { 2282 continue; 2283 } 2284 button_page = 0; 2285 for (j = 0; j < rptcnt; j++) { 2286 if (ms_rpt->usage_descr[j + i].usage_id == HID_GD_X) { 2287 idf->xpos = limit + (j * rptsz); 2288 idf->xpos /= 8; 2289 idf->xlen = rptsz; 2290 if (idf->xlen % 8) { 2291 idf->xlen = (idf->xlen / 8) + 1; 2292 } else { 2293 idf->xlen /= 8; 2294 } 2295 } else if (ms_rpt->usage_descr[j + i].usage_id == 2296 HID_GD_Y) { 2297 idf->ypos = limit + (j * rptsz); 2298 idf->ypos /= 8; 2299 idf->ylen = rptsz; 2300 if (idf->ylen % 8) { 2301 idf->ylen = (idf->ylen / 8) + 1; 2302 } else { 2303 idf->ylen /= 8; 2304 } 2305 } else if (ms_rpt->usage_descr[j + i].usage_id == 2306 HID_GD_WHEEL) { 2307 idf->zpos = limit + (j * rptsz); 2308 idf->zpos /= 8; 2309 idf->zlen = rptsz; 2310 if (idf->zlen % 8) { 2311 idf->zlen = (idf->zlen / 8) + 1; 2312 } else { 2313 idf->zlen /= 8; 2314 } 2315 } else if (ms_rpt->usage_descr[j + i].usage_page == 2316 HID_BUTTON_PAGE) { 2317 if (ms_rpt->usage_descr[j + i].usage_id != 2318 HID_USAGE_UNDEFINED) { 2319 idf->bpos = limit; 2320 } 2321 button_page = 1; 2322 break; 2323 } 2324 } 2325 2326 i += j; 2327 2328 /* enter the next valid usage */ 2329 if (button_page == 0) { 2330 i --; 2331 } 2332 limit = limit + (rptcnt * rptsz); 2333 } 2334 2335 kmem_free(ms_rpt, sizeof (hidparser_rpt_t)); 2336 2337 /* get the length of sending data */ 2338 idf->tlen = limit / 8; 2339 2340 /* Check whether X and Y are relative or absolute */ 2341 rval = hidparser_get_main_item_data_descr( 2342 usbmsp->usbms_report_descr_handle, 2343 usbmsp->usbms_rptid, 2344 HIDPARSER_ITEM_INPUT, 2345 HID_GENERIC_DESKTOP, 2346 HID_GD_X, 2347 &idf->xattr); 2348 2349 if (rval != HIDPARSER_SUCCESS) { 2350 2351 return (USB_FAILURE); 2352 } 2353 2354 /* For the time being assume that Y also has the same attr */ 2355 idf->yattr = idf->xattr; 2356 2357 /* get the logical_maximum for X and Y respectively */ 2358 if (!(idf->xattr & HID_MAIN_ITEM_RELATIVE)) { 2359 2360 /* the data format can't be parsed correctly */ 2361 if (limit % 8) { 2362 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle, 2363 "Wrong data packet include %d bits", limit); 2364 2365 return (USB_FAILURE); 2366 } 2367 if (hidparser_get_usage_attribute( 2368 usbmsp->usbms_report_descr_handle, 2369 usbmsp->usbms_rptid, 2370 HIDPARSER_ITEM_INPUT, 2371 HID_GENERIC_DESKTOP, 2372 HID_GD_X, 2373 HIDPARSER_ITEM_LOGICAL_MAXIMUM, 2374 &usbmsp->usbms_logical_Xmax) != HIDPARSER_SUCCESS) { 2375 2376 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle, 2377 "fail to get X logical max."); 2378 2379 return (USB_FAILURE); 2380 } 2381 if (hidparser_get_usage_attribute( 2382 usbmsp->usbms_report_descr_handle, 2383 usbmsp->usbms_rptid, 2384 HIDPARSER_ITEM_INPUT, 2385 HID_GENERIC_DESKTOP, 2386 HID_GD_Y, 2387 HIDPARSER_ITEM_LOGICAL_MAXIMUM, 2388 &usbmsp->usbms_logical_Ymax) != HIDPARSER_SUCCESS) { 2389 2390 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle, 2391 "fail to get Y logical max."); 2392 2393 return (USB_FAILURE); 2394 } 2395 2396 if (usbmsp->usbms_logical_Xmax == 0) { 2397 USB_DPRINTF_L3(PRINT_MASK_ALL, 2398 usbms_log_handle, 2399 "X logical max value is zero"); 2400 2401 return (USB_FAILURE); 2402 } 2403 2404 if (usbmsp->usbms_logical_Ymax == 0) { 2405 USB_DPRINTF_L3(PRINT_MASK_ALL, 2406 usbms_log_handle, 2407 "Y logical max value is zero"); 2408 2409 return (USB_FAILURE); 2410 } 2411 2412 res->height = USBMS_DEFAULT_RES_HEIGHT; 2413 res->width = USBMS_DEFAULT_RES_WIDTH; 2414 2415 /* The wheel is not supported in current remote kvms. */ 2416 usbmsp->usbms_num_wheels = 0; 2417 2418 if ((mb = allocb(sizeof (Firm_event), BPRI_HI)) == 2419 NULL) { 2420 2421 return (USB_NO_RESOURCES); 2422 } else { 2423 /* 2424 * notify the upper that it is an absolute mouse 2425 */ 2426 q = usbmsp->usbms_rq_ptr; 2427 2428 fep = (Firm_event *)mb->b_wptr; 2429 fep->id = MOUSE_TYPE_ABSOLUTE; 2430 fep->pair_type = FE_PAIR_NONE; 2431 fep->pair = NULL; 2432 fep->value = NULL; 2433 mb->b_wptr += sizeof (Firm_event); 2434 putnext(q, mb); 2435 } 2436 } else { 2437 /* general data format of relative mouse */ 2438 idf->xlen = idf->ylen = idf->zlen = 1; 2439 idf->xpos = 1; 2440 idf->ypos = 2; 2441 idf->zpos = 3; 2442 2443 /* three-byte packet for general mouse */ 2444 if (limit % 8) { 2445 USB_DPRINTF_L3(PRINT_MASK_ALL, usbms_log_handle, 2446 "Data per packet include %d bits", limit); 2447 idf->tlen = 3; 2448 } 2449 } 2450 2451 return (USB_SUCCESS); 2452 } 2453