This source file includes following definitions.
- uow_match
- uow_attach
- uow_detach
- uow_activate
- uow_ow_reset
- uow_ow_bit
- uow_ow_read_byte
- uow_ow_write_byte
- uow_ow_read_block
- uow_ow_write_block
- uow_ow_matchrom
- uow_ow_search
- uow_cmd
- uow_intr
- uow_read
- uow_write
- uow_reset
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/device.h>
26 #include <sys/kernel.h>
27 #include <sys/proc.h>
28
29 #include <dev/onewire/onewirereg.h>
30 #include <dev/onewire/onewirevar.h>
31
32 #include <dev/usb/usb.h>
33 #include <dev/usb/usbdevs.h>
34 #include <dev/usb/usbdi.h>
35 #include <dev/usb/usbdi_util.h>
36
37 #include <dev/usb/uowreg.h>
38
39 #ifdef UOW_DEBUG
40 #define DPRINTF(x) printf x
41 #else
42 #define DPRINTF(x)
43 #endif
44
45 #define UOW_TIMEOUT 1000
46
47 struct uow_softc {
48 struct device sc_dev;
49
50 struct onewire_bus sc_ow_bus;
51 struct device *sc_ow_dev;
52
53 usbd_device_handle sc_udev;
54 usbd_interface_handle sc_iface;
55 usbd_pipe_handle sc_ph_ibulk;
56 usbd_pipe_handle sc_ph_obulk;
57 usbd_pipe_handle sc_ph_intr;
58 u_int8_t sc_regs[DS2490_NREGS];
59 usbd_xfer_handle sc_xfer;
60 u_int8_t sc_fifo[DS2490_DATAFIFOSIZE];
61 };
62
63 int uow_match(struct device *, void *, void *);
64 void uow_attach(struct device *, struct device *, void *);
65 int uow_detach(struct device *, int);
66 int uow_activate(struct device *, enum devact);
67
68 struct cfdriver uow_cd = {
69 NULL, "uow", DV_DULL
70 };
71
72 const struct cfattach uow_ca = {
73 sizeof(struct uow_softc),
74 uow_match,
75 uow_attach,
76 uow_detach,
77 uow_activate,
78 };
79
80
81 static const struct usb_devno uow_devs[] = {
82 { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_USB_FOB_IBUTTON }
83 };
84
85 int uow_ow_reset(void *);
86 int uow_ow_bit(void *, int);
87 int uow_ow_read_byte(void *);
88 void uow_ow_write_byte(void *, int);
89 void uow_ow_read_block(void *, void *, int);
90 void uow_ow_write_block(void *, const void *, int);
91 void uow_ow_matchrom(void *, u_int64_t);
92 int uow_ow_search(void *, u_int64_t *, int, u_int64_t);
93
94 int uow_cmd(struct uow_softc *, int, int, int);
95 #define uow_ctlcmd(s, c, p) uow_cmd((s), DS2490_CONTROL_CMD, (c), (p))
96 #define uow_commcmd(s, c, p) uow_cmd((s), DS2490_COMM_CMD, (c), (p))
97 #define uow_modecmd(s, c, p) uow_cmd((s), DS2490_MODE_CMD, (c), (p))
98
99 void uow_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
100 int uow_read(struct uow_softc *, void *, int);
101 int uow_write(struct uow_softc *, const void *, int);
102 int uow_reset(struct uow_softc *);
103
104 int
105 uow_match(struct device *parent, void *match, void *aux)
106 {
107 struct usb_attach_arg *uaa = aux;
108
109 if (uaa->iface != NULL)
110 return (UMATCH_NONE);
111
112 return ((usb_lookup(uow_devs, uaa->vendor, uaa->product) != NULL) ?
113 UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
114 }
115
116 void
117 uow_attach(struct device *parent, struct device *self, void *aux)
118 {
119 struct uow_softc *sc = (struct uow_softc *)self;
120 struct usb_attach_arg *uaa = aux;
121 usb_interface_descriptor_t *id;
122 usb_endpoint_descriptor_t *ed;
123 char *devinfop;
124 int ep_ibulk = -1, ep_obulk = -1, ep_intr = -1;
125 struct onewirebus_attach_args oba;
126 usbd_status error;
127 int i;
128
129 sc->sc_udev = uaa->device;
130
131
132 printf("\n");
133 devinfop = usbd_devinfo_alloc(uaa->device, 0);
134 printf("%s: %s\n", sc->sc_dev.dv_xname, devinfop);
135 usbd_devinfo_free(devinfop);
136
137
138 if ((error = usbd_set_config_no(sc->sc_udev,
139 DS2490_USB_CONFIG, 0)) != 0) {
140 printf("%s: failed to set config %d: %s\n",
141 sc->sc_dev.dv_xname, DS2490_USB_CONFIG,
142 usbd_errstr(error));
143 return;
144 }
145
146
147 if ((error = usbd_device2interface_handle(sc->sc_udev,
148 DS2490_USB_IFACE, &sc->sc_iface)) != 0) {
149 printf("%s: failed to get iface %d: %s\n",
150 sc->sc_dev.dv_xname, DS2490_USB_IFACE,
151 usbd_errstr(error));
152 return;
153 }
154
155
156 id = usbd_get_interface_descriptor(sc->sc_iface);
157 for (i = 0; i < id->bNumEndpoints; i++) {
158 ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
159 if (ed == NULL) {
160 printf("%s: failed to get endpoint %d descriptor\n",
161 sc->sc_dev.dv_xname, i);
162 return;
163 }
164
165 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
166 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
167 ep_ibulk = ed->bEndpointAddress;
168 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
169 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK)
170 ep_obulk = ed->bEndpointAddress;
171 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
172 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT)
173 ep_intr = ed->bEndpointAddress;
174 }
175 if (ep_ibulk == -1 || ep_obulk == -1 || ep_intr == -1) {
176 printf("%s: missing endpoint: ibulk %d, obulk %d, intr %d\n",
177 sc->sc_dev.dv_xname, ep_ibulk, ep_obulk, ep_intr);
178 return;
179 }
180
181
182 if ((error = usbd_open_pipe(sc->sc_iface, ep_ibulk, USBD_EXCLUSIVE_USE,
183 &sc->sc_ph_ibulk)) != 0) {
184 printf("%s: failed to open bulk-in pipe: %s\n",
185 sc->sc_dev.dv_xname, usbd_errstr(error));
186 return;
187 }
188 if ((error = usbd_open_pipe(sc->sc_iface, ep_obulk, USBD_EXCLUSIVE_USE,
189 &sc->sc_ph_obulk)) != 0) {
190 printf("%s: failed to open bulk-out pipe: %s\n",
191 sc->sc_dev.dv_xname, usbd_errstr(error));
192 goto fail;
193 }
194 if ((error = usbd_open_pipe_intr(sc->sc_iface, ep_intr,
195 USBD_SHORT_XFER_OK, &sc->sc_ph_intr, sc,
196 sc->sc_regs, sizeof(sc->sc_regs), uow_intr,
197 USBD_DEFAULT_INTERVAL)) != 0) {
198 printf("%s: failed to open intr pipe: %s\n",
199 sc->sc_dev.dv_xname, usbd_errstr(error));
200 goto fail;
201 }
202
203 #if 0
204
205 if ((sc->sc_xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
206 printf("%s: failed to alloc bulk xfer\n",
207 sc->sc_dev.dv_xname);
208 goto fail;
209 }
210 #endif
211
212 memset(sc->sc_fifo, 0xff, sizeof(sc->sc_fifo));
213
214
215 uow_reset(sc);
216
217
218 sc->sc_ow_bus.bus_cookie = sc;
219 sc->sc_ow_bus.bus_reset = uow_ow_reset;
220 sc->sc_ow_bus.bus_bit = uow_ow_bit;
221 sc->sc_ow_bus.bus_read_byte = uow_ow_read_byte;
222 sc->sc_ow_bus.bus_write_byte = uow_ow_write_byte;
223 sc->sc_ow_bus.bus_read_block = uow_ow_read_block;
224 sc->sc_ow_bus.bus_write_block = uow_ow_write_block;
225 sc->sc_ow_bus.bus_matchrom = uow_ow_matchrom;
226 sc->sc_ow_bus.bus_search = uow_ow_search;
227
228 bzero(&oba, sizeof(oba));
229 oba.oba_bus = &sc->sc_ow_bus;
230 sc->sc_ow_dev = config_found(self, &oba, onewirebus_print);
231
232 return;
233
234 fail:
235 if (sc->sc_ph_ibulk != NULL)
236 usbd_close_pipe(sc->sc_ph_ibulk);
237 if (sc->sc_ph_obulk != NULL)
238 usbd_close_pipe(sc->sc_ph_obulk);
239 if (sc->sc_ph_intr != NULL)
240 usbd_close_pipe(sc->sc_ph_intr);
241 if (sc->sc_xfer != NULL)
242 usbd_free_xfer(sc->sc_xfer);
243 }
244
245 int
246 uow_detach(struct device *self, int flags)
247 {
248 struct uow_softc *sc = (struct uow_softc *)self;
249 int rv = 0, s;
250
251 s = splusb();
252
253 if (sc->sc_ph_ibulk != NULL) {
254 usbd_abort_pipe(sc->sc_ph_ibulk);
255 usbd_close_pipe(sc->sc_ph_ibulk);
256 }
257 if (sc->sc_ph_obulk != NULL) {
258 usbd_abort_pipe(sc->sc_ph_obulk);
259 usbd_close_pipe(sc->sc_ph_obulk);
260 }
261 if (sc->sc_ph_intr != NULL) {
262 usbd_abort_pipe(sc->sc_ph_intr);
263 usbd_close_pipe(sc->sc_ph_intr);
264 }
265
266 if (sc->sc_xfer != NULL)
267 usbd_free_xfer(sc->sc_xfer);
268
269 if (sc->sc_ow_dev != NULL)
270 rv = config_detach(sc->sc_ow_dev, flags);
271
272 splx(s);
273
274 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
275 &sc->sc_dev);
276
277 return (rv);
278 }
279
280 int
281 uow_activate(struct device *self, enum devact act)
282 {
283 struct uow_softc *sc = (struct uow_softc *)self;
284 int rv = 0;
285
286 switch (act) {
287 case DVACT_ACTIVATE:
288 break;
289 case DVACT_DEACTIVATE:
290 if (sc->sc_ow_dev != NULL)
291 rv = config_deactivate(sc->sc_ow_dev);
292 break;
293 }
294
295 return (rv);
296 }
297
298 int
299 uow_ow_reset(void *arg)
300 {
301 struct uow_softc *sc = arg;
302
303 if (uow_commcmd(sc, DS2490_COMM_1WIRE_RESET | DS2490_BIT_IM, 0) != 0)
304 return (1);
305
306
307 return (0);
308 }
309
310 int
311 uow_ow_bit(void *arg, int value)
312 {
313 struct uow_softc *sc = arg;
314 u_int8_t data;
315
316 if (uow_commcmd(sc, DS2490_COMM_BIT_IO | DS2490_BIT_IM |
317 (value ? DS2490_BIT_D : 0), 0) != 0)
318 return (1);
319 if (uow_read(sc, &data, 1) != 1)
320 return (1);
321
322 return (data);
323 }
324
325 int
326 uow_ow_read_byte(void *arg)
327 {
328 struct uow_softc *sc = arg;
329 u_int8_t data;
330
331 if (uow_commcmd(sc, DS2490_COMM_BYTE_IO | DS2490_BIT_IM, 0xff) != 0)
332 return (-1);
333 if (uow_read(sc, &data, 1) != 1)
334 return (-1);
335
336 return (data);
337 }
338
339 void
340 uow_ow_write_byte(void *arg, int value)
341 {
342 struct uow_softc *sc = arg;
343 u_int8_t data;
344
345 if (uow_commcmd(sc, DS2490_COMM_BYTE_IO | DS2490_BIT_IM, value) != 0)
346 return;
347 uow_read(sc, &data, sizeof(data));
348 }
349
350 void
351 uow_ow_read_block(void *arg, void *buf, int len)
352 {
353 struct uow_softc *sc = arg;
354
355 if (uow_write(sc, sc->sc_fifo, len) != 0)
356 return;
357 if (uow_commcmd(sc, DS2490_COMM_BLOCK_IO | DS2490_BIT_IM, len) != 0)
358 return;
359 uow_read(sc, buf, len);
360 }
361
362 void
363 uow_ow_write_block(void *arg, const void *buf, int len)
364 {
365 struct uow_softc *sc = arg;
366
367 if (uow_write(sc, buf, len) != 0)
368 return;
369 if (uow_commcmd(sc, DS2490_COMM_BLOCK_IO | DS2490_BIT_IM, len) != 0)
370 return;
371 }
372
373 void
374 uow_ow_matchrom(void *arg, u_int64_t rom)
375 {
376 struct uow_softc *sc = arg;
377 u_int8_t data[8];
378 int i;
379
380 for (i = 0; i < 8; i++)
381 data[i] = (rom >> (i * 8)) & 0xff;
382
383 if (uow_write(sc, data, 8) != 0)
384 return;
385 if (uow_commcmd(sc, DS2490_COMM_MATCH_ACCESS | DS2490_BIT_IM,
386 ONEWIRE_CMD_MATCH_ROM) != 0)
387 return;
388 }
389
390 int
391 uow_ow_search(void *arg, u_int64_t *buf, int size, u_int64_t startrom)
392 {
393 struct uow_softc *sc = arg;
394 u_int8_t data[8];
395 int i, rv;
396
397 for (i = 0; i < 8; i++)
398 data[i] = (startrom >> (i * 8)) & 0xff;
399
400 if (uow_write(sc, data, 8) != 0)
401 return (-1);
402 if (uow_commcmd(sc, DS2490_COMM_SEARCH_ACCESS | DS2490_BIT_IM |
403 DS2490_BIT_SM | DS2490_BIT_RST | DS2490_BIT_F, size << 8 |
404 ONEWIRE_CMD_SEARCH_ROM) != 0)
405 return (-1);
406
407 if ((rv = uow_read(sc, buf, size * 8)) == -1)
408 return (-1);
409
410 return (rv / 8);
411 }
412
413 int
414 uow_cmd(struct uow_softc *sc, int type, int cmd, int param)
415 {
416 usb_device_request_t req;
417 usbd_status error;
418
419 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
420 req.bRequest = type;
421 USETW(req.wValue, cmd);
422 USETW(req.wIndex, param);
423 USETW(req.wLength, 0);
424 if ((error = usbd_do_request(sc->sc_udev, &req, NULL)) != 0) {
425 printf("%s: cmd failed, type 0x%02x, cmd 0x%04x, "
426 "param 0x%04x: %s\n", sc->sc_dev.dv_xname, type, cmd,
427 param, usbd_errstr(error));
428 if (cmd != DS2490_CTL_RESET_DEVICE)
429 uow_reset(sc);
430 return (1);
431 }
432
433 again:
434 if (tsleep(sc->sc_regs, PRIBIO, "uowcmd",
435 (UOW_TIMEOUT * hz) / 1000) != 0) {
436 printf("%s: cmd timeout, type 0x%02x, cmd 0x%04x, "
437 "param 0x%04x\n", sc->sc_dev.dv_xname, type, cmd,
438 param);
439 return (1);
440 }
441 if ((sc->sc_regs[DS2490_ST_STFL] & DS2490_ST_STFL_IDLE) == 0)
442 goto again;
443
444 return (0);
445 }
446
447 void
448 uow_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
449 {
450 struct uow_softc *sc = priv;
451
452 if (status != USBD_NORMAL_COMPLETION) {
453 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
454 return;
455 if (status == USBD_STALLED)
456 usbd_clear_endpoint_stall_async(sc->sc_ph_intr);
457 return;
458 }
459
460 wakeup(sc->sc_regs);
461 }
462
463 int
464 uow_read(struct uow_softc *sc, void *buf, int len)
465 {
466 usbd_status error;
467 int count;
468
469
470 if (len > DS2490_DATAFIFOSIZE) {
471 printf("%s: read %d bytes, xfer too big\n",
472 sc->sc_dev.dv_xname, len);
473 return (-1);
474 }
475
476 if ((sc->sc_xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
477 printf("%s: failed to alloc xfer\n", sc->sc_dev.dv_xname);
478 return (-1);
479 }
480 usbd_setup_xfer(sc->sc_xfer, sc->sc_ph_ibulk, sc, buf, len,
481 USBD_SHORT_XFER_OK, UOW_TIMEOUT, NULL);
482 error = usbd_sync_transfer(sc->sc_xfer);
483 usbd_free_xfer(sc->sc_xfer);
484 if (error != 0) {
485 printf("%s: read failed, len %d: %s\n",
486 sc->sc_dev.dv_xname, len, usbd_errstr(error));
487 uow_reset(sc);
488 return (-1);
489 }
490
491 usbd_get_xfer_status(sc->sc_xfer, NULL, NULL, &count, &error);
492 return (count);
493 }
494
495 int
496 uow_write(struct uow_softc *sc, const void *buf, int len)
497 {
498 usbd_status error;
499
500
501 if (len > DS2490_DATAFIFOSIZE) {
502 printf("%s: write %d bytes, xfer too big\n",
503 sc->sc_dev.dv_xname, len);
504 return (1);
505 }
506
507 if ((sc->sc_xfer = usbd_alloc_xfer(sc->sc_udev)) == NULL) {
508 printf("%s: failed to alloc xfer\n", sc->sc_dev.dv_xname);
509 return (-1);
510 }
511 usbd_setup_xfer(sc->sc_xfer, sc->sc_ph_obulk, sc, (void *)buf, len, 0,
512 UOW_TIMEOUT, NULL);
513 error = usbd_sync_transfer(sc->sc_xfer);
514 usbd_free_xfer(sc->sc_xfer);
515 if (error != 0) {
516 printf("%s: write failed, len %d: %s\n",
517 sc->sc_dev.dv_xname, len, usbd_errstr(error));
518 uow_reset(sc);
519 return (1);
520 }
521
522 return (0);
523 }
524
525 int
526 uow_reset(struct uow_softc *sc)
527 {
528 return (uow_ctlcmd(sc, DS2490_CTL_RESET_DEVICE, 0));
529 }