Date: Wed, 19 Oct 2011 15:56:30 +0400 From: Alexandr Matveev <timon@timon.net.nz> To: freebsd-drivers@freebsd.org Subject: Writing HID driver Message-ID: <4E9EBAEE.2070500@timon.net.nz>
next in thread | raw e-mail | index | archive | help
Hi, I'm writing the driver for the USB keyboard, which has two interfaces: first is generic keyboard and second is HID device. If I load driver and then attach the keyboard - everything is OK. But if I attach keyboard and then kldload driver, it won't attach to the device because the default uhid driver already attached to it first. To prevent this, driver searches for uhid devices after being loaded and compares a pnpinfo string to search for suitable devices and detach them. Everything works fine, but I have two questions: 1) Is there any simpler way to do the same thing? 2) Is there a way to get device vendor & product without using device bus-specific functions? Code which I use now: DRIVER_MODULE(lkbd, uhub, lkbd_driver, lkbd_devclass, lkbd_modevent, 0); static int lkbd_modevent(module_t mod, int what, void *arg) { switch (what) { case MOD_LOAD: lkbd_detach_uhid(); break; case MOD_UNLOAD: break; default: return (EOPNOTSUPP); } return (0); } static void lkbd_detach_uhid(void) { struct u_businfo ubus; size_t ub_size = sizeof(ubus); struct u_device udev; size_t ud_size = sizeof(udev); int name2oid[2]; int oid[CTL_MAXNAME]; size_t oid_size, plen; char *name; int dev_ptr; int error; if (kernel_sysctlbyname(curthread, "hw.bus.info", &ubus, &ub_size, NULL, 0, NULL, 0) != 0) { DPRINTFN(3, "Can't get hw.bus.info sysctl node\n"); return; } /* Here is some magic from kern/kern_sysctl.c:kernel_sysctlbyname */ name2oid[0] = 0; name2oid[1] = 3; oid_size = sizeof(oid); name = "hw.bus.devices"; error = kernel_sysctl(curthread, name2oid, 2, oid, &oid_size, name, strlen(name), &plen, 0); if (error) { DPRINTFN(3, "Can't find hw.bus.devices sysctl node\n"); return; } plen /= sizeof(int); /* End of magic */ oid[plen++] = ubus.ub_generation; dev_ptr = plen++; oid[dev_ptr] = 0; while (kernel_sysctl(curthread, oid, plen, &udev, &ud_size, NULL, 0, NULL, 0) == 0) { if ( strncmp(udev.dv_drivername, "uhid", 4) == 0 && strstr(udev.dv_pnpinfo, "vendor=0x046d product=0xc228") != NULL && device_is_attached((device_t)udev.dv_handle) ) { device_detach((device_t)udev.dv_handle); } oid[dev_ptr]++; } return; } -- Alexandr Matveev
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?4E9EBAEE.2070500>