Lines 530-614
hidraw_write(struct cdev *dev, struct uio *uio, int flag)
Link Here
|
530 |
error = hid_write(sc->sc_dev, buf, size); |
530 |
error = hid_write(sc->sc_dev, buf, size); |
531 |
HIDRAW_LOCAL_FREE(local_buf, buf); |
531 |
HIDRAW_LOCAL_FREE(local_buf, buf); |
532 |
|
532 |
|
533 |
return (error); |
533 |
return (error); |
534 |
} |
534 |
} |
535 |
|
535 |
|
536 |
#ifdef COMPAT_FREEBSD32 |
536 |
#ifdef COMPAT_FREEBSD32 |
537 |
static void |
537 |
static void |
538 |
update_hgd32(const struct hidraw_gen_descriptor *hgd, |
538 |
update_hgd32(const struct hidraw_gen_descriptor *hgd, |
539 |
struct hidraw_gen_descriptor32 *hgd32) |
539 |
struct hidraw_gen_descriptor32 *hgd32) |
540 |
{ |
540 |
{ |
541 |
/* Don't update hgd_data pointer */ |
541 |
/* Don't update hgd_data pointer */ |
542 |
CP(*hgd, *hgd32, hgd_lang_id); |
542 |
CP(*hgd, *hgd32, hgd_lang_id); |
543 |
CP(*hgd, *hgd32, hgd_maxlen); |
543 |
CP(*hgd, *hgd32, hgd_maxlen); |
544 |
CP(*hgd, *hgd32, hgd_actlen); |
544 |
CP(*hgd, *hgd32, hgd_actlen); |
545 |
CP(*hgd, *hgd32, hgd_offset); |
545 |
CP(*hgd, *hgd32, hgd_offset); |
546 |
CP(*hgd, *hgd32, hgd_config_index); |
546 |
CP(*hgd, *hgd32, hgd_config_index); |
547 |
CP(*hgd, *hgd32, hgd_string_index); |
547 |
CP(*hgd, *hgd32, hgd_string_index); |
548 |
CP(*hgd, *hgd32, hgd_iface_index); |
548 |
CP(*hgd, *hgd32, hgd_iface_index); |
549 |
CP(*hgd, *hgd32, hgd_altif_index); |
549 |
CP(*hgd, *hgd32, hgd_altif_index); |
550 |
CP(*hgd, *hgd32, hgd_endpt_index); |
550 |
CP(*hgd, *hgd32, hgd_endpt_index); |
551 |
CP(*hgd, *hgd32, hgd_report_type); |
551 |
CP(*hgd, *hgd32, hgd_report_type); |
552 |
/* Don't update reserved */ |
552 |
/* Don't update reserved */ |
553 |
} |
553 |
} |
554 |
#endif |
554 |
#endif |
555 |
|
555 |
|
556 |
static int |
556 |
static int |
557 |
hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, |
557 |
hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, |
558 |
struct thread *td) |
558 |
struct thread *td) |
559 |
{ |
559 |
{ |
560 |
uint8_t local_buf[HIDRAW_LOCAL_BUFSIZE]; |
560 |
uint8_t local_buf[HIDRAW_LOCAL_BUFSIZE]; |
561 |
#ifdef COMPAT_FREEBSD32 |
561 |
#ifdef COMPAT_FREEBSD32 |
562 |
struct hidraw_gen_descriptor local_hgd; |
562 |
struct hidraw_gen_descriptor local_hgd; |
563 |
struct hidraw_gen_descriptor32 *hgd32 = NULL; |
563 |
struct hidraw_gen_descriptor32 *hgd32 = NULL; |
564 |
#endif |
564 |
#endif |
565 |
void *buf; |
565 |
void *buf; |
566 |
struct hidraw_softc *sc; |
566 |
struct hidraw_softc *sc; |
567 |
struct hidraw_device_info *hdi; |
567 |
struct hidraw_device_info *hdi; |
568 |
struct hidraw_gen_descriptor *hgd; |
568 |
struct hidraw_gen_descriptor *hgd; |
569 |
struct hidraw_report_descriptor *hrd; |
569 |
struct hidraw_report_descriptor *hrd; |
570 |
struct hidraw_devinfo *hd; |
570 |
struct hidraw_devinfo *hd; |
571 |
const char *devname; |
571 |
const char *devname; |
572 |
uint32_t size; |
572 |
uint32_t size, actsize; |
573 |
int id, len; |
573 |
int id, len; |
574 |
int error = 0; |
574 |
int error = 0; |
575 |
|
575 |
|
576 |
DPRINTFN(2, "cmd=%lx\n", cmd); |
576 |
DPRINTFN(2, "cmd=%lx\n", cmd); |
577 |
|
577 |
|
578 |
sc = dev->si_drv1; |
578 |
sc = dev->si_drv1; |
579 |
if (sc == NULL) |
579 |
if (sc == NULL) |
580 |
return (EIO); |
580 |
return (EIO); |
581 |
|
581 |
|
582 |
hgd = (struct hidraw_gen_descriptor *)addr; |
582 |
hgd = (struct hidraw_gen_descriptor *)addr; |
583 |
|
583 |
|
584 |
#ifdef COMPAT_FREEBSD32 |
584 |
#ifdef COMPAT_FREEBSD32 |
585 |
switch (cmd) { |
585 |
switch (cmd) { |
586 |
case HIDRAW_GET_REPORT_DESC32: |
586 |
case HIDRAW_GET_REPORT_DESC32: |
587 |
case HIDRAW_GET_REPORT32: |
587 |
case HIDRAW_GET_REPORT32: |
588 |
case HIDRAW_SET_REPORT_DESC32: |
588 |
case HIDRAW_SET_REPORT_DESC32: |
589 |
case HIDRAW_SET_REPORT32: |
589 |
case HIDRAW_SET_REPORT32: |
590 |
cmd = _IOC_NEWTYPE(cmd, struct hidraw_gen_descriptor); |
590 |
cmd = _IOC_NEWTYPE(cmd, struct hidraw_gen_descriptor); |
591 |
hgd32 = (struct hidraw_gen_descriptor32 *)addr; |
591 |
hgd32 = (struct hidraw_gen_descriptor32 *)addr; |
592 |
hgd = &local_hgd; |
592 |
hgd = &local_hgd; |
593 |
PTRIN_CP(*hgd32, *hgd, hgd_data); |
593 |
PTRIN_CP(*hgd32, *hgd, hgd_data); |
594 |
CP(*hgd32, *hgd, hgd_lang_id); |
594 |
CP(*hgd32, *hgd, hgd_lang_id); |
595 |
CP(*hgd32, *hgd, hgd_maxlen); |
595 |
CP(*hgd32, *hgd, hgd_maxlen); |
596 |
CP(*hgd32, *hgd, hgd_actlen); |
596 |
CP(*hgd32, *hgd, hgd_actlen); |
597 |
CP(*hgd32, *hgd, hgd_offset); |
597 |
CP(*hgd32, *hgd, hgd_offset); |
598 |
CP(*hgd32, *hgd, hgd_config_index); |
598 |
CP(*hgd32, *hgd, hgd_config_index); |
599 |
CP(*hgd32, *hgd, hgd_string_index); |
599 |
CP(*hgd32, *hgd, hgd_string_index); |
600 |
CP(*hgd32, *hgd, hgd_iface_index); |
600 |
CP(*hgd32, *hgd, hgd_iface_index); |
601 |
CP(*hgd32, *hgd, hgd_altif_index); |
601 |
CP(*hgd32, *hgd, hgd_altif_index); |
602 |
CP(*hgd32, *hgd, hgd_endpt_index); |
602 |
CP(*hgd32, *hgd, hgd_endpt_index); |
603 |
CP(*hgd32, *hgd, hgd_report_type); |
603 |
CP(*hgd32, *hgd, hgd_report_type); |
604 |
/* Don't copy reserved */ |
604 |
/* Don't copy reserved */ |
605 |
break; |
605 |
break; |
606 |
} |
606 |
} |
607 |
#endif |
607 |
#endif |
608 |
|
608 |
|
609 |
/* fixed-length ioctls handling */ |
609 |
/* fixed-length ioctls handling */ |
610 |
switch (cmd) { |
610 |
switch (cmd) { |
611 |
case FIONBIO: |
611 |
case FIONBIO: |
612 |
/* All handled in the upper FS layer. */ |
612 |
/* All handled in the upper FS layer. */ |
613 |
return (0); |
613 |
return (0); |
614 |
|
614 |
|
Lines 708-801
hidraw_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
Link Here
|
708 |
error = hid_get_report(sc->sc_dev, buf, size, NULL, |
708 |
error = hid_get_report(sc->sc_dev, buf, size, NULL, |
709 |
HID_INPUT_REPORT, sc->sc_rdesc->iid); |
709 |
HID_INPUT_REPORT, sc->sc_rdesc->iid); |
710 |
HIDRAW_LOCAL_FREE(local_buf, buf); |
710 |
HIDRAW_LOCAL_FREE(local_buf, buf); |
711 |
if (error) |
711 |
if (error) |
712 |
return (EOPNOTSUPP); |
712 |
return (EOPNOTSUPP); |
713 |
|
713 |
|
714 |
mtx_lock(&sc->sc_mtx); |
714 |
mtx_lock(&sc->sc_mtx); |
715 |
sc->sc_state.immed = true; |
715 |
sc->sc_state.immed = true; |
716 |
mtx_unlock(&sc->sc_mtx); |
716 |
mtx_unlock(&sc->sc_mtx); |
717 |
} else { |
717 |
} else { |
718 |
mtx_lock(&sc->sc_mtx); |
718 |
mtx_lock(&sc->sc_mtx); |
719 |
sc->sc_state.immed = false; |
719 |
sc->sc_state.immed = false; |
720 |
mtx_unlock(&sc->sc_mtx); |
720 |
mtx_unlock(&sc->sc_mtx); |
721 |
} |
721 |
} |
722 |
return (0); |
722 |
return (0); |
723 |
|
723 |
|
724 |
case HIDRAW_GET_REPORT: |
724 |
case HIDRAW_GET_REPORT: |
725 |
if (!(sc->sc_fflags & FREAD)) |
725 |
if (!(sc->sc_fflags & FREAD)) |
726 |
return (EPERM); |
726 |
return (EPERM); |
727 |
switch (hgd->hgd_report_type) { |
727 |
switch (hgd->hgd_report_type) { |
728 |
case HID_INPUT_REPORT: |
728 |
case HID_INPUT_REPORT: |
729 |
size = sc->sc_rdesc->isize; |
729 |
size = sc->sc_rdesc->isize; |
730 |
id = sc->sc_rdesc->iid; |
730 |
id = sc->sc_rdesc->iid; |
731 |
break; |
731 |
break; |
732 |
case HID_OUTPUT_REPORT: |
732 |
case HID_OUTPUT_REPORT: |
733 |
size = sc->sc_rdesc->osize; |
733 |
size = sc->sc_rdesc->osize; |
734 |
id = sc->sc_rdesc->oid; |
734 |
id = sc->sc_rdesc->oid; |
735 |
break; |
735 |
break; |
736 |
case HID_FEATURE_REPORT: |
736 |
case HID_FEATURE_REPORT: |
737 |
size = sc->sc_rdesc->fsize; |
737 |
size = sc->sc_rdesc->fsize; |
738 |
id = sc->sc_rdesc->fid; |
738 |
id = sc->sc_rdesc->fid; |
739 |
break; |
739 |
break; |
740 |
default: |
740 |
default: |
741 |
return (EINVAL); |
741 |
return (EINVAL); |
742 |
} |
742 |
} |
743 |
if (id != 0) { |
743 |
if (id != 0) { |
744 |
error = copyin(hgd->hgd_data, &id, 1); |
744 |
error = copyin(hgd->hgd_data, &id, 1); |
745 |
if (error != 0) |
745 |
if (error != 0) |
746 |
return (error); |
746 |
return (error); |
747 |
} |
747 |
} |
748 |
size = MIN(hgd->hgd_maxlen, size); |
748 |
size = MIN(hgd->hgd_maxlen, size); |
749 |
buf = HIDRAW_LOCAL_ALLOC(local_buf, size); |
749 |
buf = HIDRAW_LOCAL_ALLOC(local_buf, size); |
750 |
error = hid_get_report(sc->sc_dev, buf, size, NULL, |
750 |
actsize = 0; |
|
|
751 |
error = hid_get_report(sc->sc_dev, buf, size, &actsize, |
751 |
hgd->hgd_report_type, id); |
752 |
hgd->hgd_report_type, id); |
752 |
if (!error) |
753 |
if (!error) |
753 |
error = copyout(buf, hgd->hgd_data, size); |
754 |
error = copyout(buf, hgd->hgd_data, actsize); |
754 |
HIDRAW_LOCAL_FREE(local_buf, buf); |
755 |
HIDRAW_LOCAL_FREE(local_buf, buf); |
|
|
756 |
hgd->hgd_actlen = actsize; |
755 |
#ifdef COMPAT_FREEBSD32 |
757 |
#ifdef COMPAT_FREEBSD32 |
756 |
/* |
758 |
if (hgd32 != NULL) |
757 |
* HIDRAW_GET_REPORT is declared _IOWR, but hgd is not written |
759 |
update_hgd32(hgd, hgd32); |
758 |
* so we don't call update_hgd32(). |
|
|
759 |
*/ |
760 |
#endif |
760 |
#endif |
761 |
return (error); |
761 |
return (error); |
762 |
|
762 |
|
763 |
case HIDRAW_SET_REPORT: |
763 |
case HIDRAW_SET_REPORT: |
764 |
if (!(sc->sc_fflags & FWRITE)) |
764 |
if (!(sc->sc_fflags & FWRITE)) |
765 |
return (EPERM); |
765 |
return (EPERM); |
766 |
switch (hgd->hgd_report_type) { |
766 |
switch (hgd->hgd_report_type) { |
767 |
case HID_INPUT_REPORT: |
767 |
case HID_INPUT_REPORT: |
768 |
size = sc->sc_rdesc->isize; |
768 |
size = sc->sc_rdesc->isize; |
769 |
id = sc->sc_rdesc->iid; |
769 |
id = sc->sc_rdesc->iid; |
770 |
break; |
770 |
break; |
771 |
case HID_OUTPUT_REPORT: |
771 |
case HID_OUTPUT_REPORT: |
772 |
size = sc->sc_rdesc->osize; |
772 |
size = sc->sc_rdesc->osize; |
773 |
id = sc->sc_rdesc->oid; |
773 |
id = sc->sc_rdesc->oid; |
774 |
break; |
774 |
break; |
775 |
case HID_FEATURE_REPORT: |
775 |
case HID_FEATURE_REPORT: |
776 |
size = sc->sc_rdesc->fsize; |
776 |
size = sc->sc_rdesc->fsize; |
777 |
id = sc->sc_rdesc->fid; |
777 |
id = sc->sc_rdesc->fid; |
778 |
break; |
778 |
break; |
779 |
default: |
779 |
default: |
780 |
return (EINVAL); |
780 |
return (EINVAL); |
781 |
} |
781 |
} |
782 |
size = MIN(hgd->hgd_maxlen, size); |
782 |
size = MIN(hgd->hgd_maxlen, size); |
783 |
buf = HIDRAW_LOCAL_ALLOC(local_buf, size); |
783 |
buf = HIDRAW_LOCAL_ALLOC(local_buf, size); |
784 |
error = copyin(hgd->hgd_data, buf, size); |
784 |
error = copyin(hgd->hgd_data, buf, size); |
785 |
if (error == 0) { |
785 |
if (error == 0) { |
786 |
if (id != 0) |
786 |
if (id != 0) |
787 |
id = *(uint8_t *)buf; |
787 |
id = *(uint8_t *)buf; |
788 |
error = hid_set_report(sc->sc_dev, buf, size, |
788 |
error = hid_set_report(sc->sc_dev, buf, size, |
789 |
hgd->hgd_report_type, id); |
789 |
hgd->hgd_report_type, id); |
790 |
} |
790 |
} |
791 |
HIDRAW_LOCAL_FREE(local_buf, buf); |
791 |
HIDRAW_LOCAL_FREE(local_buf, buf); |
792 |
return (error); |
792 |
return (error); |
793 |
|
793 |
|
794 |
case HIDRAW_GET_REPORT_ID: |
794 |
case HIDRAW_GET_REPORT_ID: |
795 |
*(int *)addr = 0; /* XXX: we only support reportid 0? */ |
795 |
*(int *)addr = 0; /* XXX: we only support reportid 0? */ |
796 |
return (0); |
796 |
return (0); |
797 |
|
797 |
|
798 |
case HIDRAW_GET_DEVICEINFO: |
798 |
case HIDRAW_GET_DEVICEINFO: |
799 |
hdi = (struct hidraw_device_info *)addr; |
799 |
hdi = (struct hidraw_device_info *)addr; |
800 |
bzero(hdi, sizeof(struct hidraw_device_info)); |
800 |
bzero(hdi, sizeof(struct hidraw_device_info)); |
801 |
hdi->hdi_product = sc->sc_hw->idProduct; |
801 |
hdi->hdi_product = sc->sc_hw->idProduct; |