View | Details | Raw Unified | Return to bug 282790 | Differences between
and this patch

Collapse All | Expand All

(-)b/sys/dev/hid/hidraw.c (-7 / +7 lines)
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;
(-)b/sys/dev/usb/input/uhid.c (-1 / +3 lines)
Lines 594-682 uhid_ioctl(struct usb_fifo *fifo, u_long cmd, void *addr, Link Here
594
			error = EPERM;
594
			error = EPERM;
595
			break;
595
			break;
596
		}
596
		}
597
		if (*(int *)addr) {
597
		if (*(int *)addr) {
598
			/* do a test read */
598
			/* do a test read */
599
599
600
			error = uhid_get_report(sc, UHID_INPUT_REPORT,
600
			error = uhid_get_report(sc, UHID_INPUT_REPORT,
601
			    sc->sc_iid, NULL, NULL, sc->sc_isize);
601
			    sc->sc_iid, NULL, NULL, sc->sc_isize);
602
			if (error) {
602
			if (error) {
603
				break;
603
				break;
604
			}
604
			}
605
			mtx_lock(&sc->sc_mtx);
605
			mtx_lock(&sc->sc_mtx);
606
			sc->sc_flags |= UHID_FLAG_IMMED;
606
			sc->sc_flags |= UHID_FLAG_IMMED;
607
			mtx_unlock(&sc->sc_mtx);
607
			mtx_unlock(&sc->sc_mtx);
608
		} else {
608
		} else {
609
			mtx_lock(&sc->sc_mtx);
609
			mtx_lock(&sc->sc_mtx);
610
			sc->sc_flags &= ~UHID_FLAG_IMMED;
610
			sc->sc_flags &= ~UHID_FLAG_IMMED;
611
			mtx_unlock(&sc->sc_mtx);
611
			mtx_unlock(&sc->sc_mtx);
612
		}
612
		}
613
		break;
613
		break;
614
614
615
	case USB_GET_REPORT:
615
	case USB_GET_REPORT:
616
		if (!(fflags & FREAD)) {
616
		if (!(fflags & FREAD)) {
617
			error = EPERM;
617
			error = EPERM;
618
			break;
618
			break;
619
		}
619
		}
620
		switch (ugd->ugd_report_type) {
620
		switch (ugd->ugd_report_type) {
621
		case UHID_INPUT_REPORT:
621
		case UHID_INPUT_REPORT:
622
			size = sc->sc_isize;
622
			size = sc->sc_isize;
623
			id = sc->sc_iid;
623
			id = sc->sc_iid;
624
			break;
624
			break;
625
		case UHID_OUTPUT_REPORT:
625
		case UHID_OUTPUT_REPORT:
626
			size = sc->sc_osize;
626
			size = sc->sc_osize;
627
			id = sc->sc_oid;
627
			id = sc->sc_oid;
628
			break;
628
			break;
629
		case UHID_FEATURE_REPORT:
629
		case UHID_FEATURE_REPORT:
630
			size = sc->sc_fsize;
630
			size = sc->sc_fsize;
631
			id = sc->sc_fid;
631
			id = sc->sc_fid;
632
			break;
632
			break;
633
		default:
633
		default:
634
			return (EINVAL);
634
			return (EINVAL);
635
		}
635
		}
636
		size = imin(ugd->ugd_maxlen, size);
636
		if (id != 0)
637
		if (id != 0)
637
			error = copyin(ugd->ugd_data, &id, 1);
638
			error = copyin(ugd->ugd_data, &id, 1);
638
		if (error == 0)
639
		if (error == 0)
639
			error = uhid_get_report(sc, ugd->ugd_report_type, id,
640
			error = uhid_get_report(sc, ugd->ugd_report_type, id,
640
			    NULL, ugd->ugd_data, imin(ugd->ugd_maxlen, size));
641
			    NULL, ugd->ugd_data, size);
642
		ugd->ugd_actlen = size;
641
		break;
643
		break;
642
644
643
	case USB_SET_REPORT:
645
	case USB_SET_REPORT:
644
		if (!(fflags & FWRITE)) {
646
		if (!(fflags & FWRITE)) {
645
			error = EPERM;
647
			error = EPERM;
646
			break;
648
			break;
647
		}
649
		}
648
		switch (ugd->ugd_report_type) {
650
		switch (ugd->ugd_report_type) {
649
		case UHID_INPUT_REPORT:
651
		case UHID_INPUT_REPORT:
650
			size = sc->sc_isize;
652
			size = sc->sc_isize;
651
			id = sc->sc_iid;
653
			id = sc->sc_iid;
652
			break;
654
			break;
653
		case UHID_OUTPUT_REPORT:
655
		case UHID_OUTPUT_REPORT:
654
			size = sc->sc_osize;
656
			size = sc->sc_osize;
655
			id = sc->sc_oid;
657
			id = sc->sc_oid;
656
			break;
658
			break;
657
		case UHID_FEATURE_REPORT:
659
		case UHID_FEATURE_REPORT:
658
			size = sc->sc_fsize;
660
			size = sc->sc_fsize;
659
			id = sc->sc_fid;
661
			id = sc->sc_fid;
660
			break;
662
			break;
661
		default:
663
		default:
662
			return (EINVAL);
664
			return (EINVAL);
663
		}
665
		}
664
		if (id != 0)
666
		if (id != 0)
665
			error = copyin(ugd->ugd_data, &id, 1);
667
			error = copyin(ugd->ugd_data, &id, 1);
666
		if (error == 0)
668
		if (error == 0)
667
			error = uhid_set_report(sc, ugd->ugd_report_type, id,
669
			error = uhid_set_report(sc, ugd->ugd_report_type, id,
668
			    NULL, ugd->ugd_data, imin(ugd->ugd_maxlen, size));
670
			    NULL, ugd->ugd_data, imin(ugd->ugd_maxlen, size));
669
		break;
671
		break;
670
672
671
	case USB_GET_REPORT_ID:
673
	case USB_GET_REPORT_ID:
672
		*(int *)addr = 0;	/* XXX: we only support reportid 0? */
674
		*(int *)addr = 0;	/* XXX: we only support reportid 0? */
673
		break;
675
		break;
674
676
675
	default:
677
	default:
676
		error = ENOIOCTL;
678
		error = ENOIOCTL;
677
		break;
679
		break;
678
	}
680
	}
679
#ifdef COMPAT_FREEBSD32
681
#ifdef COMPAT_FREEBSD32
680
	if (ugd32 != NULL)
682
	if (ugd32 != NULL)
681
		update_usb_gen_descriptor32(ugd32, ugd);
683
		update_usb_gen_descriptor32(ugd32, ugd);
682
#endif
684
#endif

Return to bug 282790