Bug Summary

File:dev/usb/ukspan.c
Warning:line 479, column 2
Value stored to 'div' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ukspan.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/usb/ukspan.c
1/* $OpenBSD: ukspan.c,v 1.3 2020/02/17 19:29:55 jasper Exp $ */
2
3/*
4 * Copyright (c) 2019 Cody Cutler <ccutler@csail.mit.edu>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/*
20 * I don't know of any technical documentation for the Keyspan USA-19HS. I
21 * inspected the Linux driver (drivers/usb/serial/keyspan_usa90msg.h) to learn
22 * the device message format and the procedure for setting the baud rate.
23 */
24
25#include <sys/param.h>
26#include <sys/systm.h>
27#include <sys/tty.h>
28
29#include <dev/usb/usb.h>
30#include <dev/usb/usbdevs.h>
31#include <dev/usb/usbdi.h>
32#include <dev/usb/usbdi_util.h>
33
34#include <dev/usb/ucomvar.h>
35
36/*#define UKSPAN_DEBUG */
37
38#ifdef UKSPAN_DEBUG
39 #define DPRINTF(x...)do { ; } while (0) do { printf(x); } while (0)
40#else
41 #define DPRINTF(x...)do { ; } while (0) do { ; } while (0)
42#endif
43
44#define UKSPAN_PARITY_NONE0x0 0x0
45#define UKSPAN_PARITY_ODD0x08 0x08
46#define UKSPAN_PARITY_EVEN0x18 0x18
47
48#define UKSPAN_DATA_50x0 0x0
49#define UKSPAN_DATA_60x1 0x1
50#define UKSPAN_DATA_70x2 0x2
51#define UKSPAN_DATA_80x3 0x3
52
53#define UKSPAN_STOP_10x0 0x0
54#define UKSPAN_STOP_20x4 0x4
55
56#define UKSPAN_MAGIC0x2 0x2
57
58#define UKSPAN_CLOCK14769231 14769231
59
60/*
61 * The following USB indexes and endpoint addresses may be specific to the
62 * Keyspan USA19HS device
63 */
64#define UKSPAN_CONFIG_IDX1 1
65#define UKSPAN_IFACE_IDX0 0
66
67#define UKSPAN_EA_BULKIN(0x80 | 1) (UE_DIR_IN0x80 | 1)
68#define UKSPAN_EA_BULKOUT(0x00 | 1) (UE_DIR_OUT0x00 | 1)
69#define UKSPAN_EA_CONFIGIN(0x80 | 2) (UE_DIR_IN0x80 | 2)
70#define UKSPAN_EA_CONFIGOUT(0x00 | 2) (UE_DIR_OUT0x00 | 2)
71
72/* Sent to device on control out endpoint */
73struct ukspan_cmsg {
74 uint8_t setclock;
75 uint8_t baudlo;
76 uint8_t baudhi;
77 uint8_t setlcr;
78 uint8_t lcr;
79 uint8_t setrxmode;
80 uint8_t rxmode;
81 uint8_t settxmode;
82 uint8_t txmode;
83 uint8_t settxflowcontrol;
84 uint8_t txflowcontrol;
85 uint8_t setrxflowcontrol;
86 uint8_t rxflowcontrol;
87 uint8_t sendxoff;
88 uint8_t sendxon;
89 uint8_t xonchar;
90 uint8_t xoffchar;
91 uint8_t sendchar;
92 uint8_t txchar;
93 uint8_t setrts;
94 uint8_t rts;
95 uint8_t setdtr;
96 uint8_t dtr;
97
98 uint8_t rxforwardingchars;
99 uint8_t rxforwardingtimeoutms;
100 uint8_t txacksetting;
101
102 uint8_t portenabled;
103 uint8_t txflush;
104 uint8_t txbreak;
105 uint8_t loopbackmode;
106
107 uint8_t rxflush;
108 uint8_t rxforward;
109 uint8_t cancelrxoff;
110 uint8_t returnstatus;
111} __packed__attribute__((__packed__));
112
113/* Received from device on control in endpoint */
114struct ukspan_smsg {
115 uint8_t msr;
116 uint8_t cts;
117 uint8_t dcd;
118 uint8_t dsr;
119 uint8_t ri;
120 uint8_t txxoff;
121 uint8_t rxbreak;
122 uint8_t rxoverrun;
123 uint8_t rxparity;
124 uint8_t rxframe;
125 uint8_t portstate;
126 uint8_t messageack;
127 uint8_t charack;
128 uint8_t controlresp;
129} __packed__attribute__((__packed__));
130
131struct ukspan_softc {
132 struct device sc_dev;
133 struct usbd_device *udev;
134 struct usbd_interface *iface;
135 struct usbd_pipe *cout_pipe;
136 struct usbd_pipe *cin_pipe;
137 struct usbd_xfer *ixfer;
138 struct usbd_xfer *oxfer;
139 struct device *ucom_dev;
140 struct ukspan_smsg smsg;
141 struct ukspan_cmsg cmsg;
142 u_char lsr;
143 u_char msr;
144};
145
146int ukspan_match(struct device *, void *, void *);
147void ukspan_attach(struct device *, struct device *, void *);
148int ukspan_detach(struct device *, int);
149
150void ukspan_close(void *, int);
151int ukspan_open(void *, int);
152int ukspan_param(void *, int, struct termios *);
153void ukspan_set(void *, int, int, int);
154void ukspan_get_status(void *, int, u_char *, u_char *);
155
156void ukspan_cmsg_init(bool_Bool, struct ukspan_cmsg *);
157int ukspan_cmsg_send(struct ukspan_softc *);
158void ukspan_incb(struct usbd_xfer *, void *, usbd_status);
159void ukspan_outcb(struct usbd_xfer *, void *, usbd_status);
160void ukspan_destroy(struct ukspan_softc *);
161
162struct cfdriver ukspan_cd = {
163 NULL((void *)0), "ukspan", DV_DULL
164};
165
166const struct cfattach ukspan_ca = {
167 sizeof(struct ukspan_softc), ukspan_match, ukspan_attach,
168 ukspan_detach
169};
170
171static const struct usb_devno ukspan_devs[] = {
172 { USB_VENDOR_KEYSPAN0x06cd, USB_PRODUCT_KEYSPAN_USA19HS0x0121 },
173};
174
175static struct ucom_methods ukspan_methods = {
176 .ucom_get_status = ukspan_get_status,
177 .ucom_set = ukspan_set,
178 .ucom_param = ukspan_param,
179 .ucom_ioctl = NULL((void *)0),
180 .ucom_open = ukspan_open,
181 .ucom_close = ukspan_close,
182 .ucom_read = NULL((void *)0),
183 .ucom_write = NULL((void *)0),
184};
185
186int
187ukspan_match(struct device *parent, void *match, void *aux)
188{
189 struct usb_attach_arg *uaa = aux;
190
191 if (uaa->iface != NULL((void *)0))
192 return UMATCH_NONE0;
193
194 int found = usb_lookup(ukspan_devs, uaa->vendor, uaa->product)usbd_match_device((const struct usb_devno *)(ukspan_devs), sizeof
(ukspan_devs) / sizeof ((ukspan_devs)[0]), sizeof ((ukspan_devs
)[0]), (uaa->vendor), (uaa->product))
!= NULL((void *)0);
195 return found ? UMATCH_VENDOR_PRODUCT13 : UMATCH_NONE0;
196}
197
198void
199ukspan_attach(struct device *parent, struct device *self, void *aux)
200{
201 struct ukspan_softc *sc = (struct ukspan_softc *)self;
202 struct usb_attach_arg *uaa = aux;
203 struct usbd_device *dev = uaa->device;
204 struct ucom_attach_args uca = {0};
205 usb_endpoint_descriptor_t *ed;
206 const char *devname = sc->sc_dev.dv_xname;
207 usbd_status err;
208 int t1, t2, t3, t4;
209
210 DPRINTF("attach\n")do { ; } while (0);
211
212 sc->udev = dev;
213 sc->cin_pipe = sc->cout_pipe = NULL((void *)0);
214 sc->ixfer = sc->oxfer = NULL((void *)0);
215 sc->ucom_dev = NULL((void *)0);
216
217 /*
218 * Switch to configuration 1 where the transfer mode of the input
219 * endpoints is bulk instead of interrupt, as ucom expects
220 */
221 err = usbd_set_config_index(sc->udev, UKSPAN_CONFIG_IDX1, 1);
222 if (err) {
223 printf("%s: set config failed\n", devname);
224 goto fail;
225 }
226
227 err = usbd_device2interface_handle(sc->udev, UKSPAN_IFACE_IDX0,
228 &sc->iface);
229 if (err) {
230 printf("%s: get interface failed\n", devname);
231 goto fail;
232 }
233
234 ed = usbd_get_endpoint_descriptor(sc->iface, UKSPAN_EA_BULKIN(0x80 | 1));
235 t1 = UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03);
236 uca.ibufsize = UGETW(ed->wMaxPacketSize)(*(u_int16_t *)(ed->wMaxPacketSize));
237 uca.bulkin = UKSPAN_EA_BULKIN(0x80 | 1);
238
239 ed = usbd_get_endpoint_descriptor(sc->iface, UKSPAN_EA_BULKOUT(0x00 | 1));
240 t2 = UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03);
241 uca.obufsize = UGETW(ed->wMaxPacketSize)(*(u_int16_t *)(ed->wMaxPacketSize));
242 uca.bulkout = UKSPAN_EA_BULKOUT(0x00 | 1);
243
244 ed = usbd_get_endpoint_descriptor(sc->iface, UKSPAN_EA_CONFIGIN(0x80 | 2));
245 t3 = UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03);
246 if (UGETW(ed->wMaxPacketSize)(*(u_int16_t *)(ed->wMaxPacketSize)) < sizeof(struct ukspan_smsg)) {
247 printf("%s: in config packet size too small\n", devname);
248 goto fail;
249 }
250
251 ed = usbd_get_endpoint_descriptor(sc->iface, UKSPAN_EA_CONFIGOUT(0x00 | 2));
252 t4 = UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03);
253 if (UGETW(ed->wMaxPacketSize)(*(u_int16_t *)(ed->wMaxPacketSize)) < sizeof(struct ukspan_cmsg)) {
254 printf("%s: out config packet size too small\n", devname);
255 goto fail;
256 }
257
258 if (t1 != UE_BULK0x02 || t2 != UE_BULK0x02 || t3 != UE_BULK0x02 || t4 != UE_BULK0x02) {
259 printf("%s: unexpected xfertypes %x %x %x %x != %x\n", devname,
260 t1, t2, t3, t4, UE_BULK0x02);
261 goto fail;
262 }
263
264 /* Resource acquisition starts here */
265 err = usbd_open_pipe(sc->iface, UKSPAN_EA_CONFIGOUT(0x00 | 2), USBD_EXCLUSIVE_USE0x01,
266 &sc->cout_pipe);
267 if (err) {
268 printf("%s: failed to create control out pipe\n", devname);
269 goto fail;
270 }
271
272 err = usbd_open_pipe(sc->iface, UKSPAN_EA_CONFIGIN(0x80 | 2), USBD_EXCLUSIVE_USE0x01,
273 &sc->cin_pipe);
274 if (err) {
275 printf("%s: failed to create control out pipe\n", devname);
276 goto fail;
277 }
278
279 sc->ixfer = usbd_alloc_xfer(sc->udev);
280 sc->oxfer = usbd_alloc_xfer(sc->udev);
281 if (!sc->ixfer || !sc->oxfer) {
282 printf("%s: failed to allocate xfers\n", devname);
283 goto fail;
284 }
285
286 usbd_setup_xfer(sc->ixfer, sc->cin_pipe, sc, &sc->smsg,
287 sizeof(sc->smsg), 0, USBD_NO_TIMEOUT0, ukspan_incb);
288 err = usbd_transfer(sc->ixfer);
289 if (err && err != USBD_IN_PROGRESS) {
290 printf("%s: failed to start ixfer\n", devname);
291 goto fail;
292 }
293
294 uca.portno = UCOM_UNK_PORTNO-1;
295 uca.ibufsizepad = uca.ibufsize;
296 uca.opkthdrlen = 0;
297 uca.device = dev;
298 uca.iface = sc->iface;
299 uca.methods = &ukspan_methods;
300 uca.arg = sc;
301 uca.info = NULL((void *)0);
302
303 sc->ucom_dev = config_found_sm(self, &uca, ucomprint, ucomsubmatch);
304
305 DPRINTF("attach done\n")do { ; } while (0);
306
307 return;
308fail:
309 ukspan_destroy(sc);
310 usbd_deactivate(sc->udev);
311}
312
313int
314ukspan_detach(struct device *self, int flags)
315{
316 struct ukspan_softc *sc = (struct ukspan_softc *)self;
317 DPRINTF("detach\n")do { ; } while (0);
318
319 ukspan_destroy(sc);
320
321 if (sc->ucom_dev) {
322 config_detach(sc->ucom_dev, flags);
323 sc->ucom_dev = NULL((void *)0);
324 }
325 return 0;
326}
327
328void
329ukspan_outcb(struct usbd_xfer *xfer, void *priv, usbd_status status)
330{
331 struct ukspan_softc *sc = priv;
332 const char *devname = sc->sc_dev.dv_xname;
333
334 DPRINTF("outcb\n")do { ; } while (0);
335
336 if (usbd_is_dying(sc->udev)) {
337 DPRINTF("usb dying\n")do { ; } while (0);
338 return;
339 }
340 if (status != USBD_NORMAL_COMPLETION) {
341 printf("%s: oxfer failed\n", devname);
342 return;
343 }
344}
345
346void
347ukspan_incb(struct usbd_xfer *xfer, void *priv, usbd_status status)
348{
349 struct ukspan_softc *sc = priv;
350 const char *devname = sc->sc_dev.dv_xname;
351 const struct ukspan_smsg *smsg = &sc->smsg;
352 usbd_status err;
353 u_int32_t len;
354
355 DPRINTF("incb\n")do { ; } while (0);
356
357 if (usbd_is_dying(sc->udev)) {
358 printf("%s: usb dying\n", devname);
359 return;
360 }
361 if (!sc->cin_pipe || !sc->ixfer) {
362 printf("%s: no cin_pipe, but not dying?\n", devname);
363 return;
364 }
365 if (status != USBD_NORMAL_COMPLETION) {
366 if (status != USBD_NOT_STARTED && status != USBD_CANCELLED)
367 printf("%s: ixfer failed\n", devname);
368 return;
369 }
370
371 usbd_get_xfer_status(xfer, NULL((void *)0), NULL((void *)0), &len, NULL((void *)0));
372 if (len < sizeof(struct ukspan_smsg)) {
373 printf("%s: short read\n", devname);
374 return;
375 }
376
377 /* The device provides the actual MSR register */
378 sc->msr = smsg->msr;
379 /* But not LSR... */
380 sc->lsr = (smsg->rxoverrun ? ULSR_OE0x02 : 0) |
381 (smsg->rxparity ? ULSR_PE0x04 : 0) |
382 (smsg->rxframe ? ULSR_FE0x08 : 0) |
383 (smsg->rxbreak ? ULSR_BI0x10 : 0);
384 ucom_status_change((struct ucom_softc *)sc->ucom_dev);
385
386 usbd_setup_xfer(sc->ixfer, sc->cin_pipe, sc, &sc->smsg,
387 sizeof(sc->smsg), USBD_SHORT_XFER_OK0x04, USBD_NO_TIMEOUT0,
388 ukspan_incb);
389 err = usbd_transfer(sc->ixfer);
390 if (err && err != USBD_IN_PROGRESS)
391 printf("%s: usbd transfer failed\n", devname);
392}
393
394void
395ukspan_get_status(void *addr, int portno, u_char *lsr, u_char *msr)
396{
397 struct ukspan_softc *sc = addr;
398 DPRINTF("get status\n")do { ; } while (0);
399 if (lsr)
400 *lsr = sc->lsr;
401 if (msr)
402 *msr = sc->msr;
403}
404
405void
406ukspan_cmsg_init(bool_Bool opening, struct ukspan_cmsg *omsg)
407{
408 bzero(omsg, sizeof(*omsg))__builtin_bzero((omsg), (sizeof(*omsg)));
409
410 omsg->xonchar = 17;
411 omsg->xoffchar = 19;
412
413 omsg->rxforwardingchars = 16;
414 omsg->rxforwardingtimeoutms = 16;
415 omsg->txacksetting = 0;
416 omsg->txbreak = 0;
417 if (opening) {
418 omsg->portenabled = 1;
419 omsg->rxflush = 1;
420 }
421}
422
423int
424ukspan_cmsg_send(struct ukspan_softc *sc)
425{
426 const char *devname = sc->sc_dev.dv_xname;
427 usbd_status err;
428
429 usbd_setup_xfer(sc->oxfer, sc->cout_pipe, sc, &sc->cmsg,
430 sizeof(sc->cmsg), USBD_SYNCHRONOUS0x02, USBD_NO_TIMEOUT0, ukspan_outcb);
431 err = usbd_transfer(sc->oxfer);
432 if (err != USBD_NORMAL_COMPLETION) {
433 printf("%s: control xfer failed\n", devname);
434 return EIO5;
435 }
436 return 0;
437}
438
439void
440ukspan_set(void *addr, int portno, int reg, int onoff)
441{
442 struct ukspan_softc *sc = addr;
443 const char *devname = sc->sc_dev.dv_xname;
444 DPRINTF("set %#x = %#x\n", reg, onoff)do { ; } while (0);
445 int flag = !!onoff;
446 switch (reg) {
447 case UCOM_SET_DTR1:
448 sc->cmsg.setdtr = 1;
449 sc->cmsg.dtr = flag;
450 break;
451 case UCOM_SET_RTS2:
452 sc->cmsg.setrts = 1;
453 sc->cmsg.rts = flag;
454 break;
455 case UCOM_SET_BREAK3:
456 sc->cmsg.txbreak = flag;
457 break;
458 default:
459 printf("%s: unhandled reg %#x\n", devname, reg);
460 return;
461 }
462 ukspan_cmsg_send(sc);
463}
464
465int
466ukspan_param(void *addr, int portno, struct termios *ti)
467{
468 struct ukspan_softc *sc = addr;
469 const char *devname = sc->sc_dev.dv_xname;
470 struct ukspan_cmsg *cmsg = &sc->cmsg;
471 speed_t baud;
472 tcflag_t cflag;
473 u_int32_t div;
474 u_int8_t lcr;
475
476 DPRINTF("param: %#x %#x %#x\n", ti->c_ospeed, ti->c_cflag, ti->c_iflag)do { ; } while (0);
477
478 /* Set baud */
479 div = 1;
Value stored to 'div' is never read
480 baud = ti->c_ospeed;
481 switch (baud) {
482 case B300300:
483 case B600600:
484 case B12001200:
485 case B24002400:
486 case B48004800:
487 case B96009600:
488 case B1920019200:
489 case B3840038400:
490 case B5760057600:
491 case B115200115200:
492 case B230400230400:
493 div = UKSPAN_CLOCK14769231 / (baud * 16);
494 break;
495 default:
496 printf("%s: unexpected baud: %d\n", devname, baud);
497 return EINVAL22;
498 }
499
500 cmsg->setclock = 1;
501 cmsg->baudlo = div & 0xff;
502 cmsg->baudhi = div >> 8;
503
504 cmsg->setrxmode = 1;
505 cmsg->settxmode = 1;
506 if (baud > 57600)
507 cmsg->rxmode = cmsg->txmode = UKSPAN_MAGIC0x2;
508 else
509 cmsg->rxmode = cmsg->txmode = 0;
510
511 /* Set parity, data, and stop bits */
512 cflag = ti->c_cflag;
513 if ((cflag & CIGNORE0x00000001) == 0) {
514 if (cflag & PARENB0x00001000)
515 lcr = (cflag & PARODD0x00002000) ? UKSPAN_PARITY_ODD0x08 :
516 UKSPAN_PARITY_EVEN0x18;
517 else
518 lcr = UKSPAN_PARITY_NONE0x0;
519 switch (cflag & CSIZE0x00000300) {
520 case CS50x00000000:
521 lcr |= UKSPAN_DATA_50x0;
522 break;
523 case CS60x00000100:
524 lcr |= UKSPAN_DATA_60x1;
525 break;
526 case CS70x00000200:
527 lcr |= UKSPAN_DATA_70x2;
528 break;
529 case CS80x00000300:
530 lcr |= UKSPAN_DATA_80x3;
531 break;
532 }
533
534 lcr |= (cflag & CSTOPB0x00000400) ? UKSPAN_STOP_20x4 : UKSPAN_STOP_10x0;
535
536 cmsg->setlcr = 1;
537 cmsg->lcr = lcr;
538 }
539
540 /* XXX flow control? */
541
542 ukspan_cmsg_send(sc);
543 return 0;
544}
545
546int
547ukspan_open(void *addr, int portno)
548{
549 struct ukspan_softc *sc = addr;
550 int ret;
551
552 DPRINTF("open\n")do { ; } while (0);
553 if (usbd_is_dying(sc->udev)) {
554 DPRINTF("usb dying\n")do { ; } while (0);
555 return ENXIO6;
556 }
557
558 ukspan_cmsg_init(true1, &sc->cmsg);
559 ret = ukspan_cmsg_send(sc);
560 return ret;
561}
562
563void
564ukspan_close(void *addr, int portno)
565{
566 struct ukspan_softc *sc = addr;
567 DPRINTF("close\n")do { ; } while (0);
568 if (usbd_is_dying(sc->udev)) {
569 DPRINTF("usb dying\n")do { ; } while (0);
570 return;
571 }
572 ukspan_cmsg_init(false0, &sc->cmsg);
573 ukspan_cmsg_send(sc);
574}
575
576void
577ukspan_destroy(struct ukspan_softc *sc)
578{
579 DPRINTF("destroy\n")do { ; } while (0);
580 if (sc->cin_pipe) {
581 usbd_close_pipe(sc->cin_pipe);
582 sc->cin_pipe = NULL((void *)0);
583 }
584 if (sc->cout_pipe) {
585 usbd_close_pipe(sc->cout_pipe);
586 sc->cout_pipe = NULL((void *)0);
587 }
588 if (sc->oxfer) {
589 usbd_free_xfer(sc->oxfer);
590 sc->oxfer = NULL((void *)0);
591 }
592 if (sc->ixfer) {
593 usbd_free_xfer(sc->ixfer);
594 sc->ixfer = NULL((void *)0);
595 }
596}