From owner-freebsd-drivers@FreeBSD.ORG Wed Oct 19 12:06:39 2011 Return-Path: Delivered-To: freebsd-drivers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 46CCB106566C for ; Wed, 19 Oct 2011 12:06:39 +0000 (UTC) (envelope-from timon@timon.net.nz) Received: from frost.plasmahost.ru (plasmahost.ru [178.63.60.242]) by mx1.freebsd.org (Postfix) with ESMTP id D6E2C8FC0A for ; Wed, 19 Oct 2011 12:06:38 +0000 (UTC) Received: from pc121.office.masterhost.ru ([87.242.97.5]) (AUTH: PLAIN timon@timon.net.nz, SSL: TLSv1/SSLv3, 256bits, CAMELLIA256-SHA) by frost.plasmahost.ru with ESMTPSA; Wed, 19 Oct 2011 11:55:07 +0000 id 0000CD67.000000004E9EBA9D.0000E2B4 Message-ID: <4E9EBAEE.2070500@timon.net.nz> Date: Wed, 19 Oct 2011 15:56:30 +0400 From: Alexandr Matveev User-Agent: Mozilla/5.0 (X11; FreeBSD i386; rv:5.0) Gecko/20110818 Thunderbird/5.0 MIME-Version: 1.0 To: freebsd-drivers@freebsd.org Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Subject: Writing HID driver X-BeenThere: freebsd-drivers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Writing device drivers for FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 19 Oct 2011 12:06:39 -0000 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 From owner-freebsd-drivers@FreeBSD.ORG Fri Oct 21 13:06:42 2011 Return-Path: Delivered-To: freebsd-drivers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 60A481065670; Fri, 21 Oct 2011 13:06:42 +0000 (UTC) (envelope-from jhb@freebsd.org) Received: from cyrus.watson.org (cyrus.watson.org [65.122.17.42]) by mx1.freebsd.org (Postfix) with ESMTP id 381748FC18; Fri, 21 Oct 2011 13:06:42 +0000 (UTC) Received: from bigwig.baldwin.cx (66.111.2.69.static.nyinternet.net [66.111.2.69]) by cyrus.watson.org (Postfix) with ESMTPSA id B5BE846B45; Fri, 21 Oct 2011 09:06:41 -0400 (EDT) Received: from jhbbsd.localnet (unknown [209.249.190.124]) by bigwig.baldwin.cx (Postfix) with ESMTPSA id C2C5D8A06A; Fri, 21 Oct 2011 08:30:42 -0400 (EDT) From: John Baldwin To: freebsd-drivers@freebsd.org Date: Fri, 21 Oct 2011 08:30:42 -0400 User-Agent: KMail/1.13.5 (FreeBSD/8.2-CBSD-20110617; KDE/4.5.5; amd64; ; ) References: <4E9EBAEE.2070500@timon.net.nz> In-Reply-To: <4E9EBAEE.2070500@timon.net.nz> MIME-Version: 1.0 Content-Type: Text/Plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <201110210830.42285.jhb@freebsd.org> X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.2.6 (bigwig.baldwin.cx); Fri, 21 Oct 2011 08:30:42 -0400 (EDT) Cc: Warner Losh Subject: Re: Writing HID driver X-BeenThere: freebsd-drivers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Writing device drivers for FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 21 Oct 2011 13:06:42 -0000 On Wednesday, October 19, 2011 7:56:30 am Alexandr Matveev wrote: > 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? Not currently, no. > 2) Is there a way to get device vendor & product without using device > bus-specific functions? No, but you can probably implement lkbd_detach_uhid() a bit simpler by doing something like: devclass_t dc; device_t devices; int devcount, error, i; dc = devclass_find("uhid"); if (dc == NULL) return; error = devclass_get_devices(dc, &devices, &devcount); if (error) { printf("Unable to fetch uhid device list: %d\n", error); return; } for (i = 0; i < devcount; i++) { /* * Do the same checks you do in your probe routine and * detach the devices that match. */ } free(devlist, M_TEMP); -- John Baldwin