utoppy.c revision 1.24.4.9 1 1.24.4.9 skrll /* $NetBSD: utoppy.c,v 1.24.4.9 2015/10/06 21:32:15 skrll Exp $ */
2 1.1 scw
3 1.1 scw /*-
4 1.1 scw * Copyright (c) 2006 The NetBSD Foundation, Inc.
5 1.1 scw * All rights reserved.
6 1.1 scw *
7 1.1 scw * This code is derived from software contributed to The NetBSD Foundation
8 1.1 scw * by Steve C. Woodford.
9 1.1 scw *
10 1.1 scw * Redistribution and use in source and binary forms, with or without
11 1.1 scw * modification, are permitted provided that the following conditions
12 1.1 scw * are met:
13 1.1 scw * 1. Redistributions of source code must retain the above copyright
14 1.1 scw * notice, this list of conditions and the following disclaimer.
15 1.1 scw * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 scw * notice, this list of conditions and the following disclaimer in the
17 1.1 scw * documentation and/or other materials provided with the distribution.
18 1.1 scw *
19 1.1 scw * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 scw * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 scw * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 scw * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 scw * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 scw * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 scw * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 scw * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 scw * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 scw * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 scw * POSSIBILITY OF SUCH DAMAGE.
30 1.1 scw */
31 1.1 scw
32 1.1 scw #include <sys/cdefs.h>
33 1.24.4.9 skrll __KERNEL_RCSID(0, "$NetBSD: utoppy.c,v 1.24.4.9 2015/10/06 21:32:15 skrll Exp $");
34 1.1 scw
35 1.1 scw #include <sys/param.h>
36 1.1 scw #include <sys/systm.h>
37 1.1 scw #include <sys/proc.h>
38 1.1 scw #include <sys/kernel.h>
39 1.1 scw #include <sys/fcntl.h>
40 1.1 scw #include <sys/device.h>
41 1.1 scw #include <sys/ioctl.h>
42 1.1 scw #include <sys/uio.h>
43 1.1 scw #include <sys/conf.h>
44 1.1 scw #include <sys/vnode.h>
45 1.19 mrg #include <sys/bus.h>
46 1.1 scw
47 1.1 scw #include <dev/usb/usb.h>
48 1.1 scw #include <dev/usb/usbdi.h>
49 1.19 mrg #include <dev/usb/usbdivar.h>
50 1.1 scw #include <dev/usb/usbdi_util.h>
51 1.1 scw #include <dev/usb/usbdevs.h>
52 1.1 scw #include <dev/usb/usb_quirks.h>
53 1.1 scw #include <dev/usb/utoppy.h>
54 1.1 scw
55 1.1 scw #undef UTOPPY_DEBUG
56 1.1 scw #ifdef UTOPPY_DEBUG
57 1.1 scw #define UTOPPY_DBG_OPEN 0x0001
58 1.1 scw #define UTOPPY_DBG_CLOSE 0x0002
59 1.1 scw #define UTOPPY_DBG_READ 0x0004
60 1.1 scw #define UTOPPY_DBG_WRITE 0x0008
61 1.1 scw #define UTOPPY_DBG_IOCTL 0x0010
62 1.1 scw #define UTOPPY_DBG_SEND_PACKET 0x0020
63 1.1 scw #define UTOPPY_DBG_RECV_PACKET 0x0040
64 1.1 scw #define UTOPPY_DBG_ADDPATH 0x0080
65 1.1 scw #define UTOPPY_DBG_READDIR 0x0100
66 1.1 scw #define UTOPPY_DBG_DUMP 0x0200
67 1.1 scw #define DPRINTF(l, m) \
68 1.1 scw do { \
69 1.1 scw if (utoppy_debug & l) \
70 1.1 scw printf m; \
71 1.1 scw } while (/*CONSTCOND*/0)
72 1.1 scw static int utoppy_debug = 0;
73 1.1 scw static void utoppy_dump_packet(const void *, size_t);
74 1.1 scw #define DDUMP_PACKET(p, l) \
75 1.1 scw do { \
76 1.1 scw if (utoppy_debug & UTOPPY_DBG_DUMP) \
77 1.1 scw utoppy_dump_packet((p), (l)); \
78 1.1 scw } while (/*CONSTCOND*/0)
79 1.1 scw #else
80 1.1 scw #define DPRINTF(l, m) /* nothing */
81 1.1 scw #define DDUMP_PACKET(p, l) /* nothing */
82 1.1 scw #endif
83 1.1 scw
84 1.1 scw
85 1.1 scw #define UTOPPY_CONFIG_NO 1
86 1.1 scw #define UTOPPY_NUMENDPOINTS 2
87 1.1 scw
88 1.1 scw #define UTOPPY_BSIZE 0xffff
89 1.1 scw #define UTOPPY_FRAG_SIZE 0x1000
90 1.1 scw #define UTOPPY_HEADER_SIZE 8
91 1.1 scw #define UTOPPY_SHORT_TIMEOUT (500) /* 0.5 seconds */
92 1.1 scw #define UTOPPY_LONG_TIMEOUT (10 * 1000) /* 10 seconds */
93 1.1 scw
94 1.1 scw /* Protocol Commands and Responses */
95 1.1 scw #define UTOPPY_RESP_ERROR 0x0001
96 1.1 scw #define UTOPPY_CMD_ACK 0x0002
97 1.1 scw #define UTOPPY_RESP_SUCCESS UTOPPY_CMD_ACK
98 1.1 scw #define UTOPPY_CMD_CANCEL 0x0003
99 1.1 scw #define UTOPPY_CMD_READY 0x0100
100 1.1 scw #define UTOPPY_CMD_RESET 0x0101
101 1.1 scw #define UTOPPY_CMD_TURBO 0x0102
102 1.1 scw #define UTOPPY_CMD_STATS 0x1000
103 1.1 scw #define UTOPPY_RESP_STATS_DATA 0x1001
104 1.1 scw #define UTOPPY_CMD_READDIR 0x1002
105 1.1 scw #define UTOPPY_RESP_READDIR_DATA 0x1003
106 1.1 scw #define UTOPPY_RESP_READDIR_END 0x1004
107 1.1 scw #define UTOPPY_CMD_DELETE 0x1005
108 1.1 scw #define UTOPPY_CMD_RENAME 0x1006
109 1.1 scw #define UTOPPY_CMD_MKDIR 0x1007
110 1.1 scw #define UTOPPY_CMD_FILE 0x1008
111 1.1 scw #define UTOPPY_FILE_WRITE 0
112 1.1 scw #define UTOPPY_FILE_READ 1
113 1.1 scw #define UTOPPY_RESP_FILE_HEADER 0x1009
114 1.1 scw #define UTOPPY_RESP_FILE_DATA 0x100a
115 1.1 scw #define UTOPPY_RESP_FILE_END 0x100b
116 1.1 scw
117 1.1 scw enum utoppy_state {
118 1.1 scw UTOPPY_STATE_CLOSED,
119 1.1 scw UTOPPY_STATE_OPENING,
120 1.1 scw UTOPPY_STATE_IDLE,
121 1.1 scw UTOPPY_STATE_READDIR,
122 1.1 scw UTOPPY_STATE_READFILE,
123 1.1 scw UTOPPY_STATE_WRITEFILE
124 1.1 scw };
125 1.1 scw
126 1.1 scw struct utoppy_softc {
127 1.15 dyoung device_t sc_dev;
128 1.24.4.6 skrll struct usbd_device *sc_udev; /* device */
129 1.24.4.6 skrll struct usbd_interface *sc_iface; /* interface */
130 1.1 scw int sc_dying;
131 1.1 scw int sc_refcnt;
132 1.1 scw
133 1.1 scw enum utoppy_state sc_state;
134 1.1 scw u_int sc_turbo_mode;
135 1.1 scw
136 1.1 scw int sc_out;
137 1.24.4.6 skrll struct usbd_pipe *sc_out_pipe; /* bulk out pipe */
138 1.24.4.6 skrll struct usbd_xfer *sc_out_xfer;
139 1.1 scw void *sc_out_buf;
140 1.1 scw void *sc_out_data;
141 1.1 scw uint64_t sc_wr_offset;
142 1.1 scw uint64_t sc_wr_size;
143 1.1 scw
144 1.1 scw int sc_in;
145 1.24.4.6 skrll struct usbd_pipe *sc_in_pipe; /* bulk in pipe */
146 1.24.4.6 skrll struct usbd_xfer *sc_in_xfer;
147 1.1 scw void *sc_in_buf;
148 1.1 scw void *sc_in_data;
149 1.1 scw size_t sc_in_len;
150 1.1 scw u_int sc_in_offset;
151 1.1 scw };
152 1.1 scw
153 1.1 scw struct utoppy_header {
154 1.1 scw uint16_t h_len;
155 1.1 scw uint16_t h_crc;
156 1.1 scw uint16_t h_cmd2;
157 1.1 scw uint16_t h_cmd;
158 1.1 scw uint8_t h_data[0];
159 1.1 scw };
160 1.1 scw #define UTOPPY_OUT_INIT(sc) \
161 1.1 scw do { \
162 1.1 scw struct utoppy_header *_h = sc->sc_out_data; \
163 1.1 scw _h->h_len = 0; \
164 1.1 scw } while (/*CONSTCOND*/0)
165 1.1 scw
166 1.1 scw #define UTOPPY_MJD_1970 40587u /* MJD value for Jan 1 00:00:00 1970 */
167 1.1 scw
168 1.1 scw #define UTOPPY_FTYPE_DIR 1
169 1.1 scw #define UTOPPY_FTYPE_FILE 2
170 1.1 scw
171 1.1 scw #define UTOPPY_IN_DATA(sc) \
172 1.1 scw ((void*)&(((uint8_t*)(sc)->sc_in_data)[(sc)->sc_in_offset+UTOPPY_HEADER_SIZE]))
173 1.1 scw
174 1.1 scw dev_type_open(utoppyopen);
175 1.1 scw dev_type_close(utoppyclose);
176 1.1 scw dev_type_read(utoppyread);
177 1.1 scw dev_type_write(utoppywrite);
178 1.1 scw dev_type_ioctl(utoppyioctl);
179 1.1 scw
180 1.1 scw const struct cdevsw utoppy_cdevsw = {
181 1.23 dholland .d_open = utoppyopen,
182 1.23 dholland .d_close = utoppyclose,
183 1.23 dholland .d_read = utoppyread,
184 1.23 dholland .d_write = utoppywrite,
185 1.23 dholland .d_ioctl = utoppyioctl,
186 1.23 dholland .d_stop = nostop,
187 1.23 dholland .d_tty = notty,
188 1.23 dholland .d_poll = nopoll,
189 1.23 dholland .d_mmap = nommap,
190 1.23 dholland .d_kqfilter = nokqfilter,
191 1.24 dholland .d_discard = nodiscard,
192 1.23 dholland .d_flag = D_OTHER
193 1.1 scw };
194 1.1 scw
195 1.1 scw #define UTOPPYUNIT(n) (minor(n))
196 1.1 scw
197 1.15 dyoung int utoppy_match(device_t, cfdata_t, void *);
198 1.15 dyoung void utoppy_attach(device_t, device_t, void *);
199 1.15 dyoung int utoppy_detach(device_t, int);
200 1.15 dyoung int utoppy_activate(device_t, enum devact);
201 1.15 dyoung extern struct cfdriver utoppy_cd;
202 1.15 dyoung CFATTACH_DECL_NEW(utoppy, sizeof(struct utoppy_softc), utoppy_match, utoppy_attach, utoppy_detach, utoppy_activate);
203 1.1 scw
204 1.24.4.1 skrll int
205 1.15 dyoung utoppy_match(device_t parent, cfdata_t match, void *aux)
206 1.1 scw {
207 1.15 dyoung struct usb_attach_arg *uaa = aux;
208 1.1 scw
209 1.24.4.7 skrll if (uaa->uaa_vendor == USB_VENDOR_TOPFIELD &&
210 1.24.4.7 skrll uaa->uaa_product == USB_PRODUCT_TOPFIELD_TF5000PVR)
211 1.24.4.5 skrll return UMATCH_VENDOR_PRODUCT;
212 1.1 scw
213 1.24.4.5 skrll return UMATCH_NONE;
214 1.1 scw }
215 1.1 scw
216 1.24.4.1 skrll void
217 1.15 dyoung utoppy_attach(device_t parent, device_t self, void *aux)
218 1.1 scw {
219 1.15 dyoung struct utoppy_softc *sc = device_private(self);
220 1.15 dyoung struct usb_attach_arg *uaa = aux;
221 1.24.4.7 skrll struct usbd_device *dev = uaa->uaa_device;
222 1.24.4.6 skrll struct usbd_interface *iface;
223 1.1 scw usb_endpoint_descriptor_t *ed;
224 1.1 scw char *devinfop;
225 1.24.4.1 skrll uint8_t epcount;
226 1.1 scw int i;
227 1.1 scw
228 1.12 cube sc->sc_dev = self;
229 1.12 cube
230 1.13 plunky aprint_naive("\n");
231 1.13 plunky aprint_normal("\n");
232 1.13 plunky
233 1.1 scw devinfop = usbd_devinfo_alloc(dev, 0);
234 1.12 cube aprint_normal_dev(self, "%s\n", devinfop);
235 1.1 scw usbd_devinfo_free(devinfop);
236 1.1 scw
237 1.1 scw sc->sc_dying = 0;
238 1.1 scw sc->sc_refcnt = 0;
239 1.1 scw sc->sc_udev = dev;
240 1.1 scw
241 1.10 drochner if (usbd_set_config_index(dev, 0, 1)
242 1.10 drochner || usbd_device2interface_handle(dev, 0, &iface)) {
243 1.12 cube aprint_error_dev(self, "Configuration failed\n");
244 1.15 dyoung return;
245 1.10 drochner }
246 1.10 drochner
247 1.1 scw epcount = 0;
248 1.10 drochner (void) usbd_endpoint_count(iface, &epcount);
249 1.1 scw if (epcount != UTOPPY_NUMENDPOINTS) {
250 1.12 cube aprint_error_dev(self, "Expected %d endpoints, got %d\n",
251 1.12 cube UTOPPY_NUMENDPOINTS, epcount);
252 1.15 dyoung return;
253 1.1 scw }
254 1.1 scw
255 1.1 scw sc->sc_in = -1;
256 1.1 scw sc->sc_out = -1;
257 1.1 scw
258 1.1 scw for (i = 0; i < epcount; i++) {
259 1.10 drochner ed = usbd_interface2endpoint_descriptor(iface, i);
260 1.1 scw if (ed == NULL) {
261 1.12 cube aprint_error_dev(self, "couldn't get ep %d\n", i);
262 1.15 dyoung return;
263 1.1 scw }
264 1.1 scw
265 1.1 scw if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
266 1.1 scw UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
267 1.1 scw sc->sc_in = ed->bEndpointAddress;
268 1.1 scw } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
269 1.1 scw UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
270 1.1 scw sc->sc_out = ed->bEndpointAddress;
271 1.1 scw }
272 1.1 scw }
273 1.1 scw
274 1.1 scw if (sc->sc_out == -1 || sc->sc_in == -1) {
275 1.12 cube aprint_error_dev(self,
276 1.12 cube "could not find bulk in/out endpoints\n");
277 1.1 scw sc->sc_dying = 1;
278 1.15 dyoung return;
279 1.1 scw }
280 1.1 scw
281 1.10 drochner sc->sc_iface = iface;
282 1.1 scw sc->sc_udev = dev;
283 1.1 scw
284 1.24.4.9 skrll sc->sc_out_pipe = NULL;
285 1.24.4.9 skrll sc->sc_in_pipe = NULL;
286 1.24.4.9 skrll
287 1.24.4.9 skrll if (usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe)) {
288 1.24.4.9 skrll DPRINTF(UTOPPY_DBG_OPEN, ("%s: usbd_open_pipe(OUT) failed\n",
289 1.24.4.9 skrll device_xname(sc->sc_dev)));
290 1.24.4.9 skrll aprint_error_dev(self, "could not open OUT pipe\n");
291 1.24.4.9 skrll sc->sc_dying = 1;
292 1.24.4.9 skrll return;
293 1.1 scw }
294 1.1 scw
295 1.24.4.9 skrll if (usbd_open_pipe(sc->sc_iface, sc->sc_in, 0, &sc->sc_in_pipe)) {
296 1.24.4.9 skrll DPRINTF(UTOPPY_DBG_OPEN, ("%s: usbd_open_pipe(IN) failed\n",
297 1.24.4.9 skrll device_xname(sc->sc_dev)));
298 1.24.4.9 skrll aprint_error_dev(self, "could not open IN pipe\n");
299 1.24.4.9 skrll
300 1.24.4.9 skrll usbd_close_pipe(sc->sc_out_pipe);
301 1.24.4.9 skrll sc->sc_out_pipe = NULL;
302 1.24.4.9 skrll sc->sc_dying = 1;
303 1.24.4.9 skrll return;
304 1.24.4.9 skrll }
305 1.24.4.9 skrll
306 1.24.4.9 skrll int error;
307 1.24.4.9 skrll error = usbd_create_xfer(sc->sc_out_pipe, UTOPPY_FRAG_SIZE, 0, 0,
308 1.24.4.9 skrll &sc->sc_out_xfer);
309 1.24.4.9 skrll if (error) {
310 1.24.4.9 skrll aprint_error_dev(self, "could not allocate bulk out xfer\n");
311 1.24.4.9 skrll goto fail0;
312 1.1 scw }
313 1.1 scw
314 1.24.4.9 skrll error = usbd_create_xfer(sc->sc_in_pipe, UTOPPY_FRAG_SIZE,
315 1.24.4.9 skrll USBD_SHORT_XFER_OK, 0, &sc->sc_in_xfer);
316 1.24.4.9 skrll if (error) {
317 1.12 cube aprint_error_dev(self, "could not allocate bulk in xfer\n");
318 1.1 scw goto fail1;
319 1.1 scw }
320 1.1 scw
321 1.24.4.9 skrll sc->sc_out_buf = usbd_get_buffer(sc->sc_out_xfer);
322 1.24.4.9 skrll sc->sc_in_buf = usbd_get_buffer(sc->sc_in_xfer);
323 1.1 scw
324 1.1 scw usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
325 1.15 dyoung sc->sc_dev);
326 1.1 scw
327 1.15 dyoung return;
328 1.1 scw
329 1.24.4.9 skrll fail1: usbd_destroy_xfer(sc->sc_out_xfer);
330 1.1 scw sc->sc_out_xfer = NULL;
331 1.1 scw
332 1.1 scw fail0: sc->sc_dying = 1;
333 1.15 dyoung return;
334 1.1 scw }
335 1.1 scw
336 1.1 scw int
337 1.15 dyoung utoppy_activate(device_t self, enum devact act)
338 1.1 scw {
339 1.12 cube struct utoppy_softc *sc = device_private(self);
340 1.1 scw
341 1.1 scw switch (act) {
342 1.1 scw case DVACT_DEACTIVATE:
343 1.1 scw sc->sc_dying = 1;
344 1.14 dyoung return 0;
345 1.14 dyoung default:
346 1.14 dyoung return EOPNOTSUPP;
347 1.1 scw }
348 1.1 scw }
349 1.1 scw
350 1.24.4.1 skrll int
351 1.15 dyoung utoppy_detach(device_t self, int flags)
352 1.1 scw {
353 1.15 dyoung struct utoppy_softc *sc = device_private(self);
354 1.1 scw int maj, mn;
355 1.1 scw int s;
356 1.1 scw
357 1.1 scw sc->sc_dying = 1;
358 1.1 scw if (sc->sc_out_pipe != NULL)
359 1.1 scw usbd_abort_pipe(sc->sc_out_pipe);
360 1.1 scw if (sc->sc_in_pipe != NULL)
361 1.1 scw usbd_abort_pipe(sc->sc_in_pipe);
362 1.1 scw
363 1.1 scw if (sc->sc_in_xfer != NULL)
364 1.24.4.9 skrll usbd_destroy_xfer(sc->sc_in_xfer);
365 1.1 scw if (sc->sc_out_xfer != NULL)
366 1.24.4.9 skrll usbd_destroy_xfer(sc->sc_out_xfer);
367 1.1 scw
368 1.1 scw s = splusb();
369 1.1 scw if (--sc->sc_refcnt >= 0)
370 1.18 mrg usb_detach_waitold(sc->sc_dev);
371 1.1 scw splx(s);
372 1.1 scw
373 1.1 scw /* locate the major number */
374 1.1 scw maj = cdevsw_lookup_major(&utoppy_cdevsw);
375 1.1 scw
376 1.1 scw /* Nuke the vnodes for any open instances (calls close). */
377 1.21 chs mn = device_unit(self);
378 1.1 scw vdevgone(maj, mn, mn, VCHR);
379 1.1 scw
380 1.1 scw usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
381 1.15 dyoung sc->sc_dev);
382 1.1 scw
383 1.24.4.5 skrll return 0;
384 1.1 scw }
385 1.1 scw
386 1.1 scw static const uint16_t utoppy_crc16_lookup[] = {
387 1.1 scw 0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241,
388 1.1 scw 0xc601, 0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440,
389 1.1 scw 0xcc01, 0x0cc0, 0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40,
390 1.1 scw 0x0a00, 0xcac1, 0xcb81, 0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841,
391 1.1 scw 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40,
392 1.1 scw 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41,
393 1.1 scw 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641,
394 1.1 scw 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040,
395 1.1 scw 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
396 1.1 scw 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441,
397 1.1 scw 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41,
398 1.1 scw 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840,
399 1.1 scw 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41,
400 1.1 scw 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40,
401 1.1 scw 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640,
402 1.1 scw 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041,
403 1.1 scw 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240,
404 1.1 scw 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
405 1.1 scw 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41,
406 1.1 scw 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840,
407 1.1 scw 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41,
408 1.1 scw 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40,
409 1.1 scw 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640,
410 1.1 scw 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041,
411 1.1 scw 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241,
412 1.1 scw 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440,
413 1.1 scw 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
414 1.1 scw 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841,
415 1.1 scw 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40,
416 1.1 scw 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41,
417 1.1 scw 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641,
418 1.1 scw 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
419 1.1 scw };
420 1.1 scw
421 1.1 scw #define UTOPPY_CRC16(ccrc,b) \
422 1.1 scw (utoppy_crc16_lookup[((ccrc) ^ (b)) & 0xffu] ^ ((ccrc) >> 8))
423 1.1 scw
424 1.1 scw static const int utoppy_usbdstatus_lookup[] = {
425 1.1 scw 0, /* USBD_NORMAL_COMPLETION */
426 1.1 scw EINPROGRESS, /* USBD_IN_PROGRESS */
427 1.1 scw EALREADY, /* USBD_PENDING_REQUESTS */
428 1.1 scw EAGAIN, /* USBD_NOT_STARTED */
429 1.1 scw EINVAL, /* USBD_INVAL */
430 1.1 scw ENOMEM, /* USBD_NOMEM */
431 1.1 scw ECONNRESET, /* USBD_CANCELLED */
432 1.1 scw EFAULT, /* USBD_BAD_ADDRESS */
433 1.1 scw EBUSY, /* USBD_IN_USE */
434 1.1 scw EADDRNOTAVAIL, /* USBD_NO_ADDR */
435 1.1 scw ENETDOWN, /* USBD_SET_ADDR_FAILED */
436 1.1 scw EIO, /* USBD_NO_POWER */
437 1.1 scw EMLINK, /* USBD_TOO_DEEP */
438 1.1 scw EIO, /* USBD_IOERROR */
439 1.1 scw ENXIO, /* USBD_NOT_CONFIGURED */
440 1.1 scw ETIMEDOUT, /* USBD_TIMEOUT */
441 1.1 scw EBADMSG, /* USBD_SHORT_XFER */
442 1.1 scw EHOSTDOWN, /* USBD_STALLED */
443 1.1 scw EINTR /* USBD_INTERRUPTED */
444 1.1 scw };
445 1.1 scw
446 1.1 scw static __inline int
447 1.1 scw utoppy_usbd_status2errno(usbd_status err)
448 1.1 scw {
449 1.1 scw
450 1.1 scw if (err >= USBD_ERROR_MAX)
451 1.24.4.5 skrll return EFAULT;
452 1.24.4.5 skrll return utoppy_usbdstatus_lookup[err];
453 1.1 scw }
454 1.1 scw
455 1.1 scw #ifdef UTOPPY_DEBUG
456 1.1 scw static const char *
457 1.1 scw utoppy_state_string(enum utoppy_state state)
458 1.1 scw {
459 1.1 scw const char *str;
460 1.1 scw
461 1.1 scw switch (state) {
462 1.1 scw case UTOPPY_STATE_CLOSED:
463 1.1 scw str = "CLOSED";
464 1.1 scw break;
465 1.1 scw case UTOPPY_STATE_OPENING:
466 1.1 scw str = "OPENING";
467 1.1 scw break;
468 1.1 scw case UTOPPY_STATE_IDLE:
469 1.1 scw str = "IDLE";
470 1.1 scw break;
471 1.1 scw case UTOPPY_STATE_READDIR:
472 1.1 scw str = "READ DIRECTORY";
473 1.1 scw break;
474 1.1 scw case UTOPPY_STATE_READFILE:
475 1.1 scw str = "READ FILE";
476 1.1 scw break;
477 1.1 scw case UTOPPY_STATE_WRITEFILE:
478 1.1 scw str = "WRITE FILE";
479 1.1 scw break;
480 1.1 scw default:
481 1.1 scw str = "INVALID!";
482 1.1 scw break;
483 1.1 scw }
484 1.1 scw
485 1.24.4.5 skrll return str;
486 1.1 scw }
487 1.1 scw
488 1.1 scw static void
489 1.1 scw utoppy_dump_packet(const void *b, size_t len)
490 1.1 scw {
491 1.1 scw const uint8_t *buf = b, *l;
492 1.1 scw uint8_t c;
493 1.1 scw size_t i, j;
494 1.1 scw
495 1.1 scw if (len == 0)
496 1.1 scw return;
497 1.1 scw
498 1.1 scw len = min(len, 256);
499 1.1 scw
500 1.1 scw printf("00: ");
501 1.1 scw
502 1.1 scw for (i = 0, l = buf; i < len; i++) {
503 1.1 scw printf("%02x ", *buf++);
504 1.1 scw
505 1.1 scw if ((i % 16) == 15) {
506 1.1 scw for (j = 0; j < 16; j++) {
507 1.1 scw c = *l++;
508 1.1 scw if (c < ' ' || c > 0x7e)
509 1.1 scw c = '.';
510 1.1 scw printf("%c", c);
511 1.1 scw }
512 1.1 scw
513 1.1 scw printf("\n");
514 1.1 scw l = buf;
515 1.1 scw
516 1.1 scw if ((i + 1) < len)
517 1.1 scw printf("%02x: ", (u_int)i + 1);
518 1.1 scw }
519 1.1 scw }
520 1.1 scw
521 1.1 scw while ((i++ % 16) != 0)
522 1.1 scw printf(" ");
523 1.1 scw
524 1.1 scw if (l < buf) {
525 1.1 scw while (l < buf) {
526 1.1 scw c = *l++;
527 1.1 scw if (c < ' ' || c > 0x7e)
528 1.1 scw c = '.';
529 1.1 scw printf("%c", c);
530 1.1 scw }
531 1.1 scw
532 1.1 scw printf("\n");
533 1.1 scw }
534 1.1 scw }
535 1.1 scw #endif
536 1.1 scw
537 1.1 scw static usbd_status
538 1.24.4.6 skrll utoppy_bulk_transfer(struct usbd_xfer *xfer, struct usbd_pipe *pipe,
539 1.24.4.8 skrll uint16_t flags, uint32_t timeout, void *buf, uint32_t *size)
540 1.1 scw {
541 1.1 scw usbd_status err;
542 1.1 scw
543 1.24.4.9 skrll usbd_setup_xfer(xfer, 0, buf, *size, flags, timeout, NULL);
544 1.22 skrll
545 1.22 skrll err = usbd_sync_transfer_sig(xfer);
546 1.22 skrll
547 1.22 skrll usbd_get_xfer_status(xfer, NULL, NULL, size, NULL);
548 1.24.4.5 skrll return err;
549 1.1 scw }
550 1.1 scw
551 1.1 scw static int
552 1.1 scw utoppy_send_packet(struct utoppy_softc *sc, uint16_t cmd, uint32_t timeout)
553 1.1 scw {
554 1.1 scw struct utoppy_header *h;
555 1.1 scw usbd_status err;
556 1.1 scw uint32_t len;
557 1.1 scw uint16_t dlen, crc;
558 1.1 scw uint8_t *data, *e, t1, t2;
559 1.1 scw
560 1.1 scw h = sc->sc_out_data;
561 1.1 scw
562 1.1 scw DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: cmd 0x%04x, "
563 1.15 dyoung "len %d\n", device_xname(sc->sc_dev), (u_int)cmd, h->h_len));
564 1.1 scw
565 1.1 scw dlen = h->h_len;
566 1.1 scw len = dlen + UTOPPY_HEADER_SIZE;
567 1.1 scw
568 1.1 scw if (len & 1)
569 1.1 scw len++;
570 1.1 scw if ((len % 64) == 0)
571 1.1 scw len += 2;
572 1.1 scw
573 1.1 scw if (len >= UTOPPY_BSIZE) {
574 1.1 scw DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: "
575 1.15 dyoung "packet too big (%d)\n", device_xname(sc->sc_dev), (int)len));
576 1.24.4.5 skrll return EINVAL;
577 1.1 scw }
578 1.1 scw
579 1.1 scw h->h_len = htole16(dlen + UTOPPY_HEADER_SIZE);
580 1.1 scw h->h_cmd2 = 0;
581 1.1 scw h->h_cmd = htole16(cmd);
582 1.1 scw
583 1.1 scw /* The command word is part of the CRC */
584 1.1 scw crc = UTOPPY_CRC16(0, 0);
585 1.1 scw crc = UTOPPY_CRC16(crc, 0);
586 1.1 scw crc = UTOPPY_CRC16(crc, cmd >> 8);
587 1.1 scw crc = UTOPPY_CRC16(crc, cmd);
588 1.1 scw
589 1.1 scw /*
590 1.1 scw * If there is data following the header, calculate the CRC and
591 1.1 scw * byte-swap as we go.
592 1.1 scw */
593 1.1 scw if (dlen) {
594 1.1 scw data = h->h_data;
595 1.1 scw e = data + (dlen & ~1);
596 1.1 scw
597 1.1 scw do {
598 1.1 scw t1 = data[0];
599 1.1 scw t2 = data[1];
600 1.1 scw crc = UTOPPY_CRC16(crc, t1);
601 1.1 scw crc = UTOPPY_CRC16(crc, t2);
602 1.1 scw *data++ = t2;
603 1.1 scw *data++ = t1;
604 1.1 scw } while (data < e);
605 1.1 scw
606 1.1 scw if (dlen & 1) {
607 1.1 scw t1 = data[0];
608 1.1 scw crc = UTOPPY_CRC16(crc, t1);
609 1.1 scw data[1] = t1;
610 1.1 scw }
611 1.1 scw }
612 1.1 scw
613 1.1 scw h->h_crc = htole16(crc);
614 1.1 scw data = sc->sc_out_data;
615 1.1 scw
616 1.1 scw DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: total len "
617 1.15 dyoung "%d...\n", device_xname(sc->sc_dev), (int)len));
618 1.1 scw DDUMP_PACKET(data, len);
619 1.1 scw
620 1.1 scw do {
621 1.1 scw uint32_t thislen;
622 1.1 scw
623 1.1 scw thislen = min(len, UTOPPY_FRAG_SIZE);
624 1.1 scw
625 1.1 scw memcpy(sc->sc_out_buf, data, thislen);
626 1.1 scw
627 1.1 scw err = utoppy_bulk_transfer(sc->sc_out_xfer, sc->sc_out_pipe,
628 1.24.4.8 skrll 0, timeout, sc->sc_out_buf, &thislen);
629 1.1 scw
630 1.1 scw if (thislen != min(len, UTOPPY_FRAG_SIZE)) {
631 1.1 scw DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: "
632 1.1 scw "utoppy_send_packet: sent %ld, err %d\n",
633 1.15 dyoung device_xname(sc->sc_dev), (u_long)thislen, err));
634 1.1 scw }
635 1.1 scw
636 1.1 scw if (err == 0) {
637 1.1 scw len -= thislen;
638 1.1 scw data += thislen;
639 1.1 scw }
640 1.1 scw } while (err == 0 && len);
641 1.1 scw
642 1.1 scw DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: "
643 1.15 dyoung "usbd_bulk_transfer() returned %d.\n", device_xname(sc->sc_dev),err));
644 1.1 scw
645 1.24.4.5 skrll return err ? utoppy_usbd_status2errno(err) : 0;
646 1.1 scw }
647 1.1 scw
648 1.1 scw static int
649 1.1 scw utoppy_recv_packet(struct utoppy_softc *sc, uint16_t *respp, uint32_t timeout)
650 1.1 scw {
651 1.1 scw struct utoppy_header *h;
652 1.1 scw usbd_status err;
653 1.1 scw uint32_t len, thislen, requested, bytesleft;
654 1.4 scw uint16_t crc;
655 1.1 scw uint8_t *data, *e, t1, t2;
656 1.1 scw
657 1.1 scw data = sc->sc_in_data;
658 1.1 scw len = 0;
659 1.1 scw bytesleft = UTOPPY_BSIZE;
660 1.1 scw
661 1.1 scw DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: ...\n",
662 1.15 dyoung device_xname(sc->sc_dev)));
663 1.1 scw
664 1.1 scw do {
665 1.1 scw requested = thislen = min(bytesleft, UTOPPY_FRAG_SIZE);
666 1.1 scw
667 1.1 scw err = utoppy_bulk_transfer(sc->sc_in_xfer, sc->sc_in_pipe,
668 1.24.4.2 skrll USBD_SHORT_XFER_OK, timeout, sc->sc_in_buf,
669 1.24.4.8 skrll &thislen);
670 1.1 scw
671 1.1 scw DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: "
672 1.1 scw "usbd_bulk_transfer() returned %d, thislen %d, data %p\n",
673 1.15 dyoung device_xname(sc->sc_dev), err, (u_int)thislen, data));
674 1.1 scw
675 1.1 scw if (err == 0) {
676 1.1 scw memcpy(data, sc->sc_in_buf, thislen);
677 1.1 scw DDUMP_PACKET(data, thislen);
678 1.1 scw len += thislen;
679 1.1 scw bytesleft -= thislen;
680 1.1 scw data += thislen;
681 1.1 scw }
682 1.1 scw } while (err == 0 && bytesleft && thislen == requested);
683 1.1 scw
684 1.1 scw if (err)
685 1.24.4.5 skrll return utoppy_usbd_status2errno(err);
686 1.1 scw
687 1.1 scw h = sc->sc_in_data;
688 1.1 scw
689 1.1 scw DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: received %d "
690 1.15 dyoung "bytes in total to %p\n", device_xname(sc->sc_dev), (u_int)len, h));
691 1.1 scw DDUMP_PACKET(h, len);
692 1.1 scw
693 1.1 scw if (len < UTOPPY_HEADER_SIZE || len < (uint32_t)le16toh(h->h_len)) {
694 1.1 scw DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: bad "
695 1.15 dyoung " length (len %d, h_len %d)\n", device_xname(sc->sc_dev),
696 1.1 scw (int)len, le16toh(h->h_len)));
697 1.24.4.5 skrll return EIO;
698 1.1 scw }
699 1.1 scw
700 1.1 scw len = h->h_len = le16toh(h->h_len);
701 1.1 scw h->h_crc = le16toh(h->h_crc);
702 1.1 scw *respp = h->h_cmd = le16toh(h->h_cmd);
703 1.1 scw h->h_cmd2 = le16toh(h->h_cmd2);
704 1.1 scw
705 1.1 scw /*
706 1.1 scw * To maximise data throughput when transferring files, acknowledge
707 1.1 scw * data blocks as soon as we receive them. If we detect an error
708 1.1 scw * later on, we can always cancel.
709 1.1 scw */
710 1.1 scw if (*respp == UTOPPY_RESP_FILE_DATA) {
711 1.1 scw DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: "
712 1.15 dyoung "ACKing file data\n", device_xname(sc->sc_dev)));
713 1.1 scw
714 1.1 scw UTOPPY_OUT_INIT(sc);
715 1.1 scw err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
716 1.1 scw UTOPPY_SHORT_TIMEOUT);
717 1.1 scw if (err) {
718 1.1 scw DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: "
719 1.1 scw "utoppy_recv_packet: failed to ACK file data: %d\n",
720 1.15 dyoung device_xname(sc->sc_dev), err));
721 1.24.4.5 skrll return err;
722 1.1 scw }
723 1.1 scw }
724 1.1 scw
725 1.1 scw /* The command word is part of the CRC */
726 1.4 scw crc = UTOPPY_CRC16(0, h->h_cmd2 >> 8);
727 1.4 scw crc = UTOPPY_CRC16(crc, h->h_cmd2);
728 1.1 scw crc = UTOPPY_CRC16(crc, h->h_cmd >> 8);
729 1.1 scw crc = UTOPPY_CRC16(crc, h->h_cmd);
730 1.1 scw
731 1.1 scw /*
732 1.1 scw * Extract any payload, byte-swapping and calculating the CRC16
733 1.1 scw * as we go.
734 1.1 scw */
735 1.1 scw if (len > UTOPPY_HEADER_SIZE) {
736 1.1 scw data = h->h_data;
737 1.1 scw e = data + ((len & ~1) - UTOPPY_HEADER_SIZE);
738 1.1 scw
739 1.1 scw while (data < e) {
740 1.1 scw t1 = data[0];
741 1.1 scw t2 = data[1];
742 1.1 scw crc = UTOPPY_CRC16(crc, t2);
743 1.1 scw crc = UTOPPY_CRC16(crc, t1);
744 1.1 scw *data++ = t2;
745 1.1 scw *data++ = t1;
746 1.1 scw }
747 1.1 scw
748 1.1 scw if (len & 1) {
749 1.1 scw t1 = data[1];
750 1.1 scw crc = UTOPPY_CRC16(crc, t1);
751 1.1 scw *data = t1;
752 1.1 scw }
753 1.1 scw }
754 1.1 scw
755 1.1 scw sc->sc_in_len = (size_t) len - UTOPPY_HEADER_SIZE;
756 1.1 scw sc->sc_in_offset = 0;
757 1.1 scw
758 1.1 scw DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: len %d, "
759 1.15 dyoung "crc 0x%04x, hdrcrc 0x%04x\n", device_xname(sc->sc_dev),
760 1.1 scw (int)len, crc, h->h_crc));
761 1.1 scw DDUMP_PACKET(h, len);
762 1.1 scw
763 1.24.4.5 skrll return (crc == h->h_crc) ? 0 : EBADMSG;
764 1.1 scw }
765 1.1 scw
766 1.1 scw static __inline void *
767 1.1 scw utoppy_current_ptr(void *b)
768 1.1 scw {
769 1.1 scw struct utoppy_header *h = b;
770 1.1 scw
771 1.24.4.5 skrll return &h->h_data[h->h_len];
772 1.1 scw }
773 1.1 scw
774 1.1 scw static __inline void
775 1.1 scw utoppy_advance_ptr(void *b, size_t len)
776 1.1 scw {
777 1.1 scw struct utoppy_header *h = b;
778 1.1 scw
779 1.1 scw h->h_len += len;
780 1.1 scw }
781 1.1 scw
782 1.1 scw static __inline void
783 1.1 scw utoppy_add_8(struct utoppy_softc *sc, uint8_t v)
784 1.1 scw {
785 1.1 scw struct utoppy_header *h = sc->sc_out_data;
786 1.1 scw uint8_t *p;
787 1.1 scw
788 1.1 scw p = utoppy_current_ptr(h);
789 1.1 scw *p = v;
790 1.1 scw utoppy_advance_ptr(h, sizeof(v));
791 1.1 scw }
792 1.1 scw
793 1.1 scw static __inline void
794 1.1 scw utoppy_add_16(struct utoppy_softc *sc, uint16_t v)
795 1.1 scw {
796 1.1 scw struct utoppy_header *h = sc->sc_out_data;
797 1.1 scw uint8_t *p;
798 1.1 scw
799 1.1 scw p = utoppy_current_ptr(h);
800 1.1 scw *p++ = (uint8_t)(v >> 8);
801 1.1 scw *p = (uint8_t)v;
802 1.1 scw utoppy_advance_ptr(h, sizeof(v));
803 1.1 scw }
804 1.1 scw
805 1.1 scw static __inline void
806 1.1 scw utoppy_add_32(struct utoppy_softc *sc, uint32_t v)
807 1.1 scw {
808 1.1 scw struct utoppy_header *h = sc->sc_out_data;
809 1.1 scw uint8_t *p;
810 1.1 scw
811 1.1 scw p = utoppy_current_ptr(h);
812 1.1 scw *p++ = (uint8_t)(v >> 24);
813 1.1 scw *p++ = (uint8_t)(v >> 16);
814 1.1 scw *p++ = (uint8_t)(v >> 8);
815 1.1 scw *p = (uint8_t)v;
816 1.1 scw utoppy_advance_ptr(h, sizeof(v));
817 1.1 scw }
818 1.1 scw
819 1.1 scw static __inline void
820 1.1 scw utoppy_add_64(struct utoppy_softc *sc, uint64_t v)
821 1.1 scw {
822 1.1 scw struct utoppy_header *h = sc->sc_out_data;
823 1.1 scw uint8_t *p;
824 1.1 scw
825 1.1 scw p = utoppy_current_ptr(h);
826 1.1 scw *p++ = (uint8_t)(v >> 56);
827 1.1 scw *p++ = (uint8_t)(v >> 48);
828 1.1 scw *p++ = (uint8_t)(v >> 40);
829 1.1 scw *p++ = (uint8_t)(v >> 32);
830 1.1 scw *p++ = (uint8_t)(v >> 24);
831 1.1 scw *p++ = (uint8_t)(v >> 16);
832 1.1 scw *p++ = (uint8_t)(v >> 8);
833 1.1 scw *p = (uint8_t)v;
834 1.1 scw utoppy_advance_ptr(h, sizeof(v));
835 1.1 scw }
836 1.1 scw
837 1.1 scw static __inline void
838 1.1 scw utoppy_add_string(struct utoppy_softc *sc, const char *str, size_t len)
839 1.1 scw {
840 1.1 scw struct utoppy_header *h = sc->sc_out_data;
841 1.1 scw char *p;
842 1.1 scw
843 1.1 scw p = utoppy_current_ptr(h);
844 1.1 scw memset(p, 0, len);
845 1.1 scw strncpy(p, str, len);
846 1.1 scw utoppy_advance_ptr(h, len);
847 1.1 scw }
848 1.1 scw
849 1.1 scw static int
850 1.1 scw utoppy_add_path(struct utoppy_softc *sc, const char *path, int putlen)
851 1.1 scw {
852 1.1 scw struct utoppy_header *h = sc->sc_out_data;
853 1.1 scw uint8_t *p, *str, *s;
854 1.1 scw size_t len;
855 1.1 scw int err;
856 1.1 scw
857 1.1 scw p = utoppy_current_ptr(h);
858 1.1 scw
859 1.1 scw str = putlen ? (p + sizeof(uint16_t)) : p;
860 1.1 scw
861 1.1 scw err = copyinstr(path, str, UTOPPY_MAX_FILENAME_LEN, &len);
862 1.1 scw
863 1.1 scw DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: err %d, len %d\n",
864 1.1 scw err, (int)len));
865 1.1 scw
866 1.1 scw if (err)
867 1.24.4.5 skrll return err;
868 1.1 scw
869 1.1 scw if (len < 2)
870 1.24.4.5 skrll return EINVAL;
871 1.1 scw
872 1.1 scw /*
873 1.1 scw * copyinstr(9) has already copied the terminating NUL character,
874 1.1 scw * but we append another one in case we have to pad the length
875 1.1 scw * later on.
876 1.1 scw */
877 1.1 scw str[len] = '\0';
878 1.1 scw
879 1.1 scw /*
880 1.1 scw * The Toppy uses backslash as the directory separator, so convert
881 1.1 scw * all forward slashes.
882 1.1 scw */
883 1.1 scw for (s = &str[len - 2]; s >= str; s--)
884 1.1 scw if (*s == '/')
885 1.1 scw *s = '\\';
886 1.1 scw
887 1.1 scw if ((len + h->h_len) & 1)
888 1.1 scw len++;
889 1.1 scw
890 1.1 scw if (putlen)
891 1.1 scw utoppy_add_16(sc, len);
892 1.1 scw
893 1.1 scw utoppy_advance_ptr(h, len);
894 1.1 scw
895 1.1 scw DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: final len %d\n",
896 1.1 scw (u_int)len));
897 1.1 scw
898 1.24.4.5 skrll return 0;
899 1.1 scw }
900 1.1 scw
901 1.1 scw static __inline int
902 1.1 scw utoppy_get_8(struct utoppy_softc *sc, uint8_t *vp)
903 1.1 scw {
904 1.1 scw uint8_t *p;
905 1.1 scw
906 1.1 scw if (sc->sc_in_len < sizeof(*vp))
907 1.24.4.5 skrll return 1;
908 1.1 scw
909 1.1 scw p = UTOPPY_IN_DATA(sc);
910 1.1 scw *vp = *p;
911 1.1 scw sc->sc_in_offset += sizeof(*vp);
912 1.1 scw sc->sc_in_len -= sizeof(*vp);
913 1.24.4.5 skrll return 0;
914 1.1 scw }
915 1.1 scw
916 1.1 scw static __inline int
917 1.1 scw utoppy_get_16(struct utoppy_softc *sc, uint16_t *vp)
918 1.1 scw {
919 1.1 scw uint16_t v;
920 1.1 scw uint8_t *p;
921 1.1 scw
922 1.1 scw if (sc->sc_in_len < sizeof(v))
923 1.24.4.5 skrll return 1;
924 1.1 scw
925 1.1 scw p = UTOPPY_IN_DATA(sc);
926 1.1 scw v = *p++;
927 1.1 scw v = (v << 8) | *p;
928 1.1 scw *vp = v;
929 1.1 scw sc->sc_in_offset += sizeof(v);
930 1.1 scw sc->sc_in_len -= sizeof(v);
931 1.24.4.5 skrll return 0;
932 1.1 scw }
933 1.1 scw
934 1.1 scw static __inline int
935 1.1 scw utoppy_get_32(struct utoppy_softc *sc, uint32_t *vp)
936 1.1 scw {
937 1.1 scw uint32_t v;
938 1.1 scw uint8_t *p;
939 1.1 scw
940 1.1 scw if (sc->sc_in_len < sizeof(v))
941 1.24.4.5 skrll return 1;
942 1.1 scw
943 1.1 scw p = UTOPPY_IN_DATA(sc);
944 1.1 scw v = *p++;
945 1.1 scw v = (v << 8) | *p++;
946 1.1 scw v = (v << 8) | *p++;
947 1.1 scw v = (v << 8) | *p;
948 1.1 scw *vp = v;
949 1.1 scw sc->sc_in_offset += sizeof(v);
950 1.1 scw sc->sc_in_len -= sizeof(v);
951 1.24.4.5 skrll return 0;
952 1.1 scw }
953 1.1 scw
954 1.1 scw static __inline int
955 1.1 scw utoppy_get_64(struct utoppy_softc *sc, uint64_t *vp)
956 1.1 scw {
957 1.1 scw uint64_t v;
958 1.1 scw uint8_t *p;
959 1.1 scw
960 1.1 scw if (sc->sc_in_len < sizeof(v))
961 1.24.4.5 skrll return 1;
962 1.1 scw
963 1.1 scw p = UTOPPY_IN_DATA(sc);
964 1.1 scw v = *p++;
965 1.1 scw v = (v << 8) | *p++;
966 1.1 scw v = (v << 8) | *p++;
967 1.1 scw v = (v << 8) | *p++;
968 1.1 scw v = (v << 8) | *p++;
969 1.1 scw v = (v << 8) | *p++;
970 1.1 scw v = (v << 8) | *p++;
971 1.1 scw v = (v << 8) | *p;
972 1.1 scw *vp = v;
973 1.1 scw sc->sc_in_offset += sizeof(v);
974 1.1 scw sc->sc_in_len -= sizeof(v);
975 1.24.4.5 skrll return 0;
976 1.1 scw }
977 1.1 scw
978 1.1 scw static __inline int
979 1.1 scw utoppy_get_string(struct utoppy_softc *sc, char *str, size_t len)
980 1.1 scw {
981 1.1 scw char *p;
982 1.1 scw
983 1.1 scw if (sc->sc_in_len < len)
984 1.24.4.5 skrll return 1;
985 1.1 scw
986 1.1 scw memset(str, 0, len);
987 1.1 scw p = UTOPPY_IN_DATA(sc);
988 1.1 scw strncpy(str, p, len);
989 1.1 scw sc->sc_in_offset += len;
990 1.1 scw sc->sc_in_len -= len;
991 1.24.4.5 skrll return 0;
992 1.1 scw }
993 1.1 scw
994 1.1 scw static int
995 1.1 scw utoppy_command(struct utoppy_softc *sc, uint16_t cmd, int timeout,
996 1.1 scw uint16_t *presp)
997 1.1 scw {
998 1.1 scw int err;
999 1.1 scw
1000 1.1 scw err = utoppy_send_packet(sc, cmd, timeout);
1001 1.1 scw if (err)
1002 1.24.4.5 skrll return err;
1003 1.1 scw
1004 1.1 scw err = utoppy_recv_packet(sc, presp, timeout);
1005 1.1 scw if (err == EBADMSG) {
1006 1.1 scw UTOPPY_OUT_INIT(sc);
1007 1.1 scw utoppy_send_packet(sc, UTOPPY_RESP_ERROR, timeout);
1008 1.1 scw }
1009 1.1 scw
1010 1.24.4.5 skrll return err;
1011 1.1 scw }
1012 1.1 scw
1013 1.1 scw static int
1014 1.1 scw utoppy_timestamp_decode(struct utoppy_softc *sc, time_t *tp)
1015 1.1 scw {
1016 1.1 scw uint16_t mjd;
1017 1.1 scw uint8_t hour, minute, sec;
1018 1.1 scw uint32_t rv;
1019 1.1 scw
1020 1.1 scw if (utoppy_get_16(sc, &mjd) || utoppy_get_8(sc, &hour) ||
1021 1.1 scw utoppy_get_8(sc, &minute) || utoppy_get_8(sc, &sec))
1022 1.24.4.5 skrll return 1;
1023 1.1 scw
1024 1.1 scw if (mjd == 0xffffu && hour == 0xffu && minute == 0xffu && sec == 0xffu){
1025 1.1 scw *tp = 0;
1026 1.24.4.5 skrll return 0;
1027 1.1 scw }
1028 1.1 scw
1029 1.1 scw rv = (mjd < UTOPPY_MJD_1970) ? UTOPPY_MJD_1970 : (uint32_t) mjd;
1030 1.1 scw
1031 1.1 scw /* Calculate seconds since 1970 */
1032 1.1 scw rv = (rv - UTOPPY_MJD_1970) * 60 * 60 * 24;
1033 1.1 scw
1034 1.1 scw /* Add in the hours, minutes, and seconds */
1035 1.1 scw rv += (uint32_t)hour * 60 * 60;
1036 1.1 scw rv += (uint32_t)minute * 60;
1037 1.1 scw rv += sec;
1038 1.1 scw *tp = (time_t)rv;
1039 1.1 scw
1040 1.24.4.5 skrll return 0;
1041 1.1 scw }
1042 1.1 scw
1043 1.1 scw static void
1044 1.1 scw utoppy_timestamp_encode(struct utoppy_softc *sc, time_t t)
1045 1.1 scw {
1046 1.1 scw u_int mjd, hour, minute;
1047 1.1 scw
1048 1.1 scw mjd = t / (60 * 60 * 24);
1049 1.1 scw t -= mjd * 60 * 60 * 24;
1050 1.1 scw
1051 1.1 scw hour = t / (60 * 60);
1052 1.1 scw t -= hour * 60 * 60;
1053 1.1 scw
1054 1.1 scw minute = t / 60;
1055 1.1 scw t -= minute * 60;
1056 1.1 scw
1057 1.1 scw utoppy_add_16(sc, mjd + UTOPPY_MJD_1970);
1058 1.1 scw utoppy_add_8(sc, hour);
1059 1.1 scw utoppy_add_8(sc, minute);
1060 1.1 scw utoppy_add_8(sc, t);
1061 1.1 scw }
1062 1.1 scw
1063 1.1 scw static int
1064 1.1 scw utoppy_turbo_mode(struct utoppy_softc *sc, int state)
1065 1.1 scw {
1066 1.1 scw uint16_t r;
1067 1.1 scw int err;
1068 1.1 scw
1069 1.1 scw UTOPPY_OUT_INIT(sc);
1070 1.1 scw utoppy_add_32(sc, state);
1071 1.1 scw
1072 1.1 scw err = utoppy_command(sc, UTOPPY_CMD_TURBO, UTOPPY_SHORT_TIMEOUT, &r);
1073 1.1 scw if (err)
1074 1.24.4.5 skrll return err;
1075 1.1 scw
1076 1.24.4.5 skrll return (r == UTOPPY_RESP_SUCCESS) ? 0 : EIO;
1077 1.1 scw }
1078 1.1 scw
1079 1.1 scw static int
1080 1.1 scw utoppy_check_ready(struct utoppy_softc *sc)
1081 1.1 scw {
1082 1.1 scw uint16_t r;
1083 1.1 scw int err;
1084 1.1 scw
1085 1.1 scw UTOPPY_OUT_INIT(sc);
1086 1.1 scw
1087 1.1 scw err = utoppy_command(sc, UTOPPY_CMD_READY, UTOPPY_LONG_TIMEOUT, &r);
1088 1.1 scw if (err)
1089 1.24.4.5 skrll return err;
1090 1.1 scw
1091 1.24.4.5 skrll return (r == UTOPPY_RESP_SUCCESS) ? 0 : EIO;
1092 1.1 scw }
1093 1.1 scw
1094 1.1 scw static int
1095 1.1 scw utoppy_cancel(struct utoppy_softc *sc)
1096 1.1 scw {
1097 1.1 scw uint16_t r;
1098 1.1 scw int err, i;
1099 1.1 scw
1100 1.1 scw /*
1101 1.1 scw * Issue the cancel command serveral times. the Toppy doesn't
1102 1.1 scw * always respond to the first.
1103 1.1 scw */
1104 1.1 scw for (i = 0; i < 3; i++) {
1105 1.1 scw UTOPPY_OUT_INIT(sc);
1106 1.1 scw err = utoppy_command(sc, UTOPPY_CMD_CANCEL,
1107 1.1 scw UTOPPY_SHORT_TIMEOUT, &r);
1108 1.1 scw if (err == 0 && r == UTOPPY_RESP_SUCCESS)
1109 1.1 scw break;
1110 1.1 scw err = ETIMEDOUT;
1111 1.1 scw }
1112 1.1 scw
1113 1.1 scw if (err)
1114 1.24.4.5 skrll return err;
1115 1.1 scw
1116 1.1 scw /*
1117 1.1 scw * Make sure turbo mode is off, otherwise the Toppy will not
1118 1.1 scw * respond to remote control input.
1119 1.1 scw */
1120 1.1 scw (void) utoppy_turbo_mode(sc, 0);
1121 1.1 scw
1122 1.1 scw sc->sc_state = UTOPPY_STATE_IDLE;
1123 1.24.4.5 skrll return 0;
1124 1.1 scw }
1125 1.1 scw
1126 1.1 scw static int
1127 1.1 scw utoppy_stats(struct utoppy_softc *sc, struct utoppy_stats *us)
1128 1.1 scw {
1129 1.1 scw uint32_t hsize, hfree;
1130 1.1 scw uint16_t r;
1131 1.1 scw int err;
1132 1.1 scw
1133 1.1 scw UTOPPY_OUT_INIT(sc);
1134 1.1 scw err = utoppy_command(sc, UTOPPY_CMD_STATS, UTOPPY_LONG_TIMEOUT, &r);
1135 1.1 scw if (err)
1136 1.24.4.5 skrll return err;
1137 1.1 scw
1138 1.1 scw if (r != UTOPPY_RESP_STATS_DATA)
1139 1.24.4.5 skrll return EIO;
1140 1.1 scw
1141 1.1 scw if (utoppy_get_32(sc, &hsize) || utoppy_get_32(sc, &hfree))
1142 1.24.4.5 skrll return EIO;
1143 1.1 scw
1144 1.1 scw us->us_hdd_size = hsize;
1145 1.1 scw us->us_hdd_size *= 1024;
1146 1.1 scw us->us_hdd_free = hfree;
1147 1.1 scw us->us_hdd_free *= 1024;
1148 1.1 scw
1149 1.24.4.5 skrll return 0;
1150 1.1 scw }
1151 1.1 scw
1152 1.1 scw static int
1153 1.1 scw utoppy_readdir_next(struct utoppy_softc *sc)
1154 1.1 scw {
1155 1.1 scw uint16_t resp;
1156 1.1 scw int err;
1157 1.1 scw
1158 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: running...\n",
1159 1.15 dyoung device_xname(sc->sc_dev)));
1160 1.1 scw
1161 1.1 scw /*
1162 1.1 scw * Fetch the next READDIR response
1163 1.1 scw */
1164 1.1 scw err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT);
1165 1.1 scw if (err) {
1166 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1167 1.1 scw "utoppy_recv_packet() returned %d\n",
1168 1.15 dyoung device_xname(sc->sc_dev), err));
1169 1.1 scw if (err == EBADMSG) {
1170 1.1 scw UTOPPY_OUT_INIT(sc);
1171 1.1 scw utoppy_send_packet(sc, UTOPPY_RESP_ERROR,
1172 1.1 scw UTOPPY_LONG_TIMEOUT);
1173 1.1 scw }
1174 1.1 scw utoppy_cancel(sc);
1175 1.24.4.5 skrll return err;
1176 1.1 scw }
1177 1.1 scw
1178 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1179 1.1 scw "utoppy_recv_packet() returned %d, len %ld\n",
1180 1.15 dyoung device_xname(sc->sc_dev), err, (u_long)sc->sc_in_len));
1181 1.1 scw
1182 1.1 scw switch (resp) {
1183 1.1 scw case UTOPPY_RESP_READDIR_DATA:
1184 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1185 1.15 dyoung "UTOPPY_RESP_READDIR_DATA\n", device_xname(sc->sc_dev)));
1186 1.1 scw
1187 1.1 scw UTOPPY_OUT_INIT(sc);
1188 1.1 scw err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
1189 1.1 scw UTOPPY_LONG_TIMEOUT);
1190 1.1 scw if (err) {
1191 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1192 1.1 scw "utoppy_send_packet(ACK) returned %d\n",
1193 1.15 dyoung device_xname(sc->sc_dev), err));
1194 1.1 scw utoppy_cancel(sc);
1195 1.24.4.5 skrll return err;
1196 1.1 scw }
1197 1.1 scw sc->sc_state = UTOPPY_STATE_READDIR;
1198 1.1 scw sc->sc_in_offset = 0;
1199 1.1 scw break;
1200 1.1 scw
1201 1.1 scw case UTOPPY_RESP_READDIR_END:
1202 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1203 1.15 dyoung "UTOPPY_RESP_READDIR_END\n", device_xname(sc->sc_dev)));
1204 1.1 scw
1205 1.1 scw UTOPPY_OUT_INIT(sc);
1206 1.1 scw utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT);
1207 1.1 scw sc->sc_state = UTOPPY_STATE_IDLE;
1208 1.1 scw sc->sc_in_len = 0;
1209 1.1 scw break;
1210 1.1 scw
1211 1.1 scw default:
1212 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1213 1.15 dyoung "bad response: 0x%x\n", device_xname(sc->sc_dev), resp));
1214 1.1 scw sc->sc_state = UTOPPY_STATE_IDLE;
1215 1.1 scw sc->sc_in_len = 0;
1216 1.24.4.5 skrll return EIO;
1217 1.1 scw }
1218 1.1 scw
1219 1.24.4.5 skrll return 0;
1220 1.1 scw }
1221 1.1 scw
1222 1.1 scw static size_t
1223 1.1 scw utoppy_readdir_decode(struct utoppy_softc *sc, struct utoppy_dirent *ud)
1224 1.1 scw {
1225 1.1 scw uint8_t ftype;
1226 1.1 scw
1227 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: bytes left"
1228 1.15 dyoung " %d\n", device_xname(sc->sc_dev), (int)sc->sc_in_len));
1229 1.1 scw
1230 1.1 scw if (utoppy_timestamp_decode(sc, &ud->ud_mtime) ||
1231 1.1 scw utoppy_get_8(sc, &ftype) || utoppy_get_64(sc, &ud->ud_size) ||
1232 1.1 scw utoppy_get_string(sc, ud->ud_path, UTOPPY_MAX_FILENAME_LEN + 1) ||
1233 1.1 scw utoppy_get_32(sc, &ud->ud_attributes)) {
1234 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: no "
1235 1.15 dyoung "more to decode\n", device_xname(sc->sc_dev)));
1236 1.24.4.5 skrll return 0;
1237 1.1 scw }
1238 1.1 scw
1239 1.1 scw switch (ftype) {
1240 1.1 scw case UTOPPY_FTYPE_DIR:
1241 1.1 scw ud->ud_type = UTOPPY_DIRENT_DIRECTORY;
1242 1.1 scw break;
1243 1.1 scw case UTOPPY_FTYPE_FILE:
1244 1.1 scw ud->ud_type = UTOPPY_DIRENT_FILE;
1245 1.1 scw break;
1246 1.1 scw default:
1247 1.1 scw ud->ud_type = UTOPPY_DIRENT_UNKNOWN;
1248 1.1 scw break;
1249 1.1 scw }
1250 1.1 scw
1251 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: %s '%s', "
1252 1.15 dyoung "size %lld, time 0x%08lx, attr 0x%08x\n", device_xname(sc->sc_dev),
1253 1.1 scw (ftype == UTOPPY_FTYPE_DIR) ? "DIR" :
1254 1.1 scw ((ftype == UTOPPY_FTYPE_FILE) ? "FILE" : "UNKNOWN"), ud->ud_path,
1255 1.1 scw ud->ud_size, (u_long)ud->ud_mtime, ud->ud_attributes));
1256 1.1 scw
1257 1.24.4.5 skrll return 1;
1258 1.1 scw }
1259 1.1 scw
1260 1.1 scw static int
1261 1.1 scw utoppy_readfile_next(struct utoppy_softc *sc)
1262 1.1 scw {
1263 1.1 scw uint64_t off;
1264 1.1 scw uint16_t resp;
1265 1.1 scw int err;
1266 1.1 scw
1267 1.1 scw err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT);
1268 1.1 scw if (err) {
1269 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1270 1.1 scw "utoppy_recv_packet() returned %d\n",
1271 1.15 dyoung device_xname(sc->sc_dev), err));
1272 1.1 scw utoppy_cancel(sc);
1273 1.24.4.5 skrll return err;
1274 1.1 scw }
1275 1.1 scw
1276 1.1 scw switch (resp) {
1277 1.1 scw case UTOPPY_RESP_FILE_HEADER:
1278 1.1 scw /* ACK it */
1279 1.1 scw UTOPPY_OUT_INIT(sc);
1280 1.1 scw err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
1281 1.1 scw UTOPPY_LONG_TIMEOUT);
1282 1.1 scw if (err) {
1283 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1284 1.1 scw "utoppy_send_packet(UTOPPY_CMD_ACK) returned %d\n",
1285 1.15 dyoung device_xname(sc->sc_dev), err));
1286 1.1 scw utoppy_cancel(sc);
1287 1.24.4.5 skrll return err;
1288 1.1 scw }
1289 1.1 scw
1290 1.1 scw sc->sc_in_len = 0;
1291 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1292 1.15 dyoung "FILE_HEADER done\n", device_xname(sc->sc_dev)));
1293 1.1 scw break;
1294 1.1 scw
1295 1.1 scw case UTOPPY_RESP_FILE_DATA:
1296 1.1 scw /* Already ACK'd */
1297 1.1 scw if (utoppy_get_64(sc, &off)) {
1298 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1299 1.1 scw "UTOPPY_RESP_FILE_DATA did not provide offset\n",
1300 1.15 dyoung device_xname(sc->sc_dev)));
1301 1.1 scw utoppy_cancel(sc);
1302 1.24.4.5 skrll return EBADMSG;
1303 1.1 scw }
1304 1.1 scw
1305 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1306 1.1 scw "UTOPPY_RESP_FILE_DATA: offset %lld, bytes left %ld\n",
1307 1.15 dyoung device_xname(sc->sc_dev), off, (u_long)sc->sc_in_len));
1308 1.1 scw break;
1309 1.1 scw
1310 1.1 scw case UTOPPY_RESP_FILE_END:
1311 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1312 1.1 scw "UTOPPY_RESP_FILE_END: sending ACK\n",
1313 1.15 dyoung device_xname(sc->sc_dev)));
1314 1.1 scw UTOPPY_OUT_INIT(sc);
1315 1.1 scw utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT);
1316 1.1 scw /*FALLTHROUGH*/
1317 1.1 scw
1318 1.1 scw case UTOPPY_RESP_SUCCESS:
1319 1.1 scw sc->sc_state = UTOPPY_STATE_IDLE;
1320 1.1 scw (void) utoppy_turbo_mode(sc, 0);
1321 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: all "
1322 1.15 dyoung "done\n", device_xname(sc->sc_dev)));
1323 1.1 scw break;
1324 1.1 scw
1325 1.1 scw case UTOPPY_RESP_ERROR:
1326 1.1 scw default:
1327 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: bad "
1328 1.15 dyoung "response code 0x%0x\n", device_xname(sc->sc_dev), resp));
1329 1.1 scw utoppy_cancel(sc);
1330 1.24.4.5 skrll return EIO;
1331 1.1 scw }
1332 1.1 scw
1333 1.24.4.5 skrll return 0;
1334 1.1 scw }
1335 1.1 scw
1336 1.1 scw int
1337 1.8 christos utoppyopen(dev_t dev, int flag, int mode,
1338 1.8 christos struct lwp *l)
1339 1.1 scw {
1340 1.1 scw struct utoppy_softc *sc;
1341 1.1 scw int error = 0;
1342 1.1 scw
1343 1.15 dyoung sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev));
1344 1.15 dyoung if (sc == NULL)
1345 1.15 dyoung return ENXIO;
1346 1.1 scw
1347 1.1 scw if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying)
1348 1.24.4.5 skrll return ENXIO;
1349 1.1 scw
1350 1.1 scw if (sc->sc_state != UTOPPY_STATE_CLOSED) {
1351 1.1 scw DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: already open\n",
1352 1.15 dyoung device_xname(sc->sc_dev)));
1353 1.24.4.5 skrll return EBUSY;
1354 1.1 scw }
1355 1.1 scw
1356 1.1 scw DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: opening...\n",
1357 1.15 dyoung device_xname(sc->sc_dev)));
1358 1.1 scw
1359 1.1 scw sc->sc_refcnt++;
1360 1.1 scw sc->sc_state = UTOPPY_STATE_OPENING;
1361 1.1 scw sc->sc_turbo_mode = 0;
1362 1.24.4.3 skrll sc->sc_out_data = kmem_alloc(UTOPPY_BSIZE + 1, KM_SLEEP);
1363 1.1 scw if (sc->sc_out_data == NULL) {
1364 1.1 scw error = ENOMEM;
1365 1.1 scw goto error;
1366 1.1 scw }
1367 1.1 scw
1368 1.24.4.3 skrll sc->sc_in_data = kmem_alloc(UTOPPY_BSIZE + 1, KM_SLEEP);
1369 1.1 scw if (sc->sc_in_data == NULL) {
1370 1.24.4.3 skrll kmem_free(sc->sc_out_data, UTOPPY_BSIZE + 1);
1371 1.1 scw sc->sc_out_data = NULL;
1372 1.1 scw error = ENOMEM;
1373 1.1 scw goto error;
1374 1.1 scw }
1375 1.1 scw
1376 1.1 scw if ((error = utoppy_cancel(sc)) != 0)
1377 1.1 scw goto error;
1378 1.1 scw
1379 1.1 scw if ((error = utoppy_check_ready(sc)) != 0) {
1380 1.1 scw DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: utoppy_check_ready()"
1381 1.15 dyoung " returned %d\n", device_xname(sc->sc_dev), error));
1382 1.1 scw }
1383 1.1 scw
1384 1.24.4.9 skrll error:
1385 1.1 scw sc->sc_state = error ? UTOPPY_STATE_CLOSED : UTOPPY_STATE_IDLE;
1386 1.1 scw
1387 1.1 scw DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: done. error %d, new state "
1388 1.15 dyoung "'%s'\n", device_xname(sc->sc_dev), error,
1389 1.1 scw utoppy_state_string(sc->sc_state)));
1390 1.1 scw
1391 1.1 scw if (--sc->sc_refcnt < 0)
1392 1.18 mrg usb_detach_wakeupold(sc->sc_dev);
1393 1.1 scw
1394 1.24.4.5 skrll return error;
1395 1.1 scw }
1396 1.1 scw
1397 1.1 scw int
1398 1.8 christos utoppyclose(dev_t dev, int flag, int mode,
1399 1.8 christos struct lwp *l)
1400 1.1 scw {
1401 1.1 scw struct utoppy_softc *sc;
1402 1.1 scw usbd_status err;
1403 1.1 scw
1404 1.15 dyoung sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev));
1405 1.1 scw
1406 1.1 scw DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: closing...\n",
1407 1.15 dyoung device_xname(sc->sc_dev)));
1408 1.1 scw
1409 1.1 scw if (sc->sc_state < UTOPPY_STATE_IDLE) {
1410 1.1 scw /* We are being forced to close before the open completed. */
1411 1.1 scw DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: not properly open:"
1412 1.15 dyoung " %s\n", device_xname(sc->sc_dev),
1413 1.1 scw utoppy_state_string(sc->sc_state)));
1414 1.24.4.5 skrll return 0;
1415 1.1 scw }
1416 1.1 scw
1417 1.3 christos if (sc->sc_out_data)
1418 1.3 christos (void) utoppy_cancel(sc);
1419 1.1 scw
1420 1.1 scw if (sc->sc_out_pipe != NULL) {
1421 1.1 scw if ((err = usbd_abort_pipe(sc->sc_out_pipe)) != 0)
1422 1.1 scw printf("usbd_abort_pipe(OUT) returned %d\n", err);
1423 1.1 scw if ((err = usbd_close_pipe(sc->sc_out_pipe)) != 0)
1424 1.1 scw printf("usbd_close_pipe(OUT) returned %d\n", err);
1425 1.1 scw sc->sc_out_pipe = NULL;
1426 1.1 scw }
1427 1.1 scw
1428 1.1 scw if (sc->sc_in_pipe != NULL) {
1429 1.1 scw if ((err = usbd_abort_pipe(sc->sc_in_pipe)) != 0)
1430 1.1 scw printf("usbd_abort_pipe(IN) returned %d\n", err);
1431 1.1 scw if ((err = usbd_close_pipe(sc->sc_in_pipe)) != 0)
1432 1.1 scw printf("usbd_close_pipe(IN) returned %d\n", err);
1433 1.1 scw sc->sc_in_pipe = NULL;
1434 1.1 scw }
1435 1.1 scw
1436 1.1 scw if (sc->sc_out_data) {
1437 1.24.4.3 skrll kmem_free(sc->sc_out_data, UTOPPY_BSIZE + 1);
1438 1.1 scw sc->sc_out_data = NULL;
1439 1.1 scw }
1440 1.1 scw
1441 1.1 scw if (sc->sc_in_data) {
1442 1.24.4.3 skrll kmem_free(sc->sc_in_data, UTOPPY_BSIZE + 1);
1443 1.1 scw sc->sc_in_data = NULL;
1444 1.1 scw }
1445 1.1 scw
1446 1.1 scw sc->sc_state = UTOPPY_STATE_CLOSED;
1447 1.1 scw
1448 1.1 scw DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: done.\n",
1449 1.15 dyoung device_xname(sc->sc_dev)));
1450 1.1 scw
1451 1.24.4.5 skrll return 0;
1452 1.1 scw }
1453 1.1 scw
1454 1.1 scw int
1455 1.8 christos utoppyread(dev_t dev, struct uio *uio, int flags)
1456 1.1 scw {
1457 1.1 scw struct utoppy_softc *sc;
1458 1.1 scw struct utoppy_dirent ud;
1459 1.1 scw size_t len;
1460 1.1 scw int err;
1461 1.1 scw
1462 1.15 dyoung sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev));
1463 1.1 scw
1464 1.1 scw if (sc->sc_dying)
1465 1.24.4.5 skrll return EIO;
1466 1.1 scw
1467 1.1 scw sc->sc_refcnt++;
1468 1.1 scw
1469 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: reading: state '%s'\n",
1470 1.15 dyoung device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state)));
1471 1.1 scw
1472 1.1 scw switch (sc->sc_state) {
1473 1.1 scw case UTOPPY_STATE_READDIR:
1474 1.1 scw err = 0;
1475 1.1 scw while (err == 0 && uio->uio_resid >= sizeof(ud) &&
1476 1.1 scw sc->sc_state != UTOPPY_STATE_IDLE) {
1477 1.1 scw if (utoppy_readdir_decode(sc, &ud) == 0)
1478 1.1 scw err = utoppy_readdir_next(sc);
1479 1.1 scw else
1480 1.1 scw if ((err = uiomove(&ud, sizeof(ud), uio)) != 0)
1481 1.24.4.1 skrll utoppy_cancel(sc);
1482 1.1 scw }
1483 1.1 scw break;
1484 1.1 scw
1485 1.1 scw case UTOPPY_STATE_READFILE:
1486 1.1 scw err = 0;
1487 1.1 scw while (err == 0 && uio->uio_resid > 0 &&
1488 1.1 scw sc->sc_state != UTOPPY_STATE_IDLE) {
1489 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: READFILE: "
1490 1.1 scw "resid %ld, bytes_left %ld\n",
1491 1.15 dyoung device_xname(sc->sc_dev), (u_long)uio->uio_resid,
1492 1.1 scw (u_long)sc->sc_in_len));
1493 1.1 scw
1494 1.1 scw if (sc->sc_in_len == 0 &&
1495 1.1 scw (err = utoppy_readfile_next(sc)) != 0) {
1496 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: "
1497 1.1 scw "READFILE: utoppy_readfile_next returned "
1498 1.15 dyoung "%d\n", device_xname(sc->sc_dev), err));
1499 1.1 scw break;
1500 1.1 scw }
1501 1.1 scw
1502 1.1 scw len = min(uio->uio_resid, sc->sc_in_len);
1503 1.1 scw if (len) {
1504 1.1 scw err = uiomove(UTOPPY_IN_DATA(sc), len, uio);
1505 1.1 scw if (err == 0) {
1506 1.1 scw sc->sc_in_offset += len;
1507 1.1 scw sc->sc_in_len -= len;
1508 1.1 scw }
1509 1.1 scw }
1510 1.1 scw }
1511 1.1 scw break;
1512 1.1 scw
1513 1.1 scw case UTOPPY_STATE_IDLE:
1514 1.1 scw err = 0;
1515 1.1 scw break;
1516 1.1 scw
1517 1.1 scw case UTOPPY_STATE_WRITEFILE:
1518 1.1 scw err = EBUSY;
1519 1.1 scw break;
1520 1.1 scw
1521 1.1 scw default:
1522 1.1 scw err = EIO;
1523 1.1 scw break;
1524 1.1 scw }
1525 1.1 scw
1526 1.1 scw DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: done. err %d, state '%s'\n",
1527 1.15 dyoung device_xname(sc->sc_dev), err, utoppy_state_string(sc->sc_state)));
1528 1.1 scw
1529 1.1 scw if (--sc->sc_refcnt < 0)
1530 1.18 mrg usb_detach_wakeupold(sc->sc_dev);
1531 1.1 scw
1532 1.24.4.5 skrll return err;
1533 1.1 scw }
1534 1.1 scw
1535 1.1 scw int
1536 1.8 christos utoppywrite(dev_t dev, struct uio *uio, int flags)
1537 1.1 scw {
1538 1.1 scw struct utoppy_softc *sc;
1539 1.1 scw uint16_t resp;
1540 1.1 scw size_t len;
1541 1.1 scw int err;
1542 1.1 scw
1543 1.15 dyoung sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev));
1544 1.1 scw
1545 1.1 scw if (sc->sc_dying)
1546 1.24.4.5 skrll return EIO;
1547 1.1 scw
1548 1.1 scw switch(sc->sc_state) {
1549 1.1 scw case UTOPPY_STATE_WRITEFILE:
1550 1.1 scw break;
1551 1.1 scw
1552 1.1 scw case UTOPPY_STATE_IDLE:
1553 1.24.4.5 skrll return 0;
1554 1.1 scw
1555 1.1 scw default:
1556 1.24.4.5 skrll return EIO;
1557 1.1 scw }
1558 1.1 scw
1559 1.1 scw sc->sc_refcnt++;
1560 1.1 scw err = 0;
1561 1.1 scw
1562 1.1 scw DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: PRE-WRITEFILE: resid %ld, "
1563 1.15 dyoung "wr_size %lld, wr_offset %lld\n", device_xname(sc->sc_dev),
1564 1.1 scw (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset));
1565 1.1 scw
1566 1.1 scw while (sc->sc_state == UTOPPY_STATE_WRITEFILE &&
1567 1.1 scw (len = min(uio->uio_resid, sc->sc_wr_size)) != 0) {
1568 1.1 scw
1569 1.1 scw len = min(len, UTOPPY_BSIZE - (UTOPPY_HEADER_SIZE +
1570 1.1 scw sizeof(uint64_t) + 3));
1571 1.1 scw
1572 1.1 scw DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove(%ld)\n",
1573 1.15 dyoung device_xname(sc->sc_dev), (u_long)len));
1574 1.1 scw
1575 1.1 scw UTOPPY_OUT_INIT(sc);
1576 1.1 scw utoppy_add_64(sc, sc->sc_wr_offset);
1577 1.1 scw
1578 1.1 scw err = uiomove(utoppy_current_ptr(sc->sc_out_data), len, uio);
1579 1.1 scw if (err) {
1580 1.1 scw DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove() "
1581 1.15 dyoung "returned %d\n", device_xname(sc->sc_dev), err));
1582 1.1 scw break;
1583 1.1 scw }
1584 1.1 scw
1585 1.1 scw utoppy_advance_ptr(sc->sc_out_data, len);
1586 1.1 scw
1587 1.1 scw err = utoppy_command(sc, UTOPPY_RESP_FILE_DATA,
1588 1.1 scw UTOPPY_LONG_TIMEOUT, &resp);
1589 1.1 scw if (err) {
1590 1.1 scw DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
1591 1.1 scw "utoppy_command(UTOPPY_RESP_FILE_DATA) "
1592 1.15 dyoung "returned %d\n", device_xname(sc->sc_dev), err));
1593 1.1 scw break;
1594 1.1 scw }
1595 1.1 scw if (resp != UTOPPY_RESP_SUCCESS) {
1596 1.1 scw DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
1597 1.1 scw "utoppy_command(UTOPPY_RESP_FILE_DATA) returned "
1598 1.15 dyoung "bad response 0x%x\n", device_xname(sc->sc_dev),
1599 1.1 scw resp));
1600 1.1 scw utoppy_cancel(sc);
1601 1.1 scw err = EIO;
1602 1.1 scw break;
1603 1.1 scw }
1604 1.1 scw
1605 1.1 scw sc->sc_wr_offset += len;
1606 1.1 scw sc->sc_wr_size -= len;
1607 1.1 scw }
1608 1.1 scw
1609 1.1 scw DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: POST-WRITEFILE: resid %ld,"
1610 1.15 dyoung " wr_size %lld, wr_offset %lld, err %d\n", device_xname(sc->sc_dev),
1611 1.1 scw (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset, err));
1612 1.1 scw
1613 1.1 scw if (err == 0 && sc->sc_wr_size == 0) {
1614 1.1 scw DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: sending "
1615 1.15 dyoung "FILE_END...\n", device_xname(sc->sc_dev)));
1616 1.1 scw UTOPPY_OUT_INIT(sc);
1617 1.1 scw err = utoppy_command(sc, UTOPPY_RESP_FILE_END,
1618 1.1 scw UTOPPY_LONG_TIMEOUT, &resp);
1619 1.1 scw if (err) {
1620 1.1 scw DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
1621 1.1 scw "utoppy_command(UTOPPY_RESP_FILE_END) returned "
1622 1.15 dyoung "%d\n", device_xname(sc->sc_dev), err));
1623 1.1 scw
1624 1.1 scw utoppy_cancel(sc);
1625 1.1 scw }
1626 1.1 scw
1627 1.1 scw sc->sc_state = UTOPPY_STATE_IDLE;
1628 1.1 scw DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: state %s\n",
1629 1.15 dyoung device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state)));
1630 1.1 scw }
1631 1.1 scw
1632 1.1 scw if (--sc->sc_refcnt < 0)
1633 1.18 mrg usb_detach_wakeupold(sc->sc_dev);
1634 1.1 scw
1635 1.24.4.5 skrll return err;
1636 1.1 scw }
1637 1.1 scw
1638 1.1 scw int
1639 1.9 christos utoppyioctl(dev_t dev, u_long cmd, void *data, int flag,
1640 1.8 christos struct lwp *l)
1641 1.1 scw {
1642 1.1 scw struct utoppy_softc *sc;
1643 1.1 scw struct utoppy_rename *ur;
1644 1.1 scw struct utoppy_readfile *urf;
1645 1.1 scw struct utoppy_writefile *uw;
1646 1.1 scw char uwf[UTOPPY_MAX_FILENAME_LEN + 1], *uwfp;
1647 1.1 scw uint16_t resp;
1648 1.1 scw int err;
1649 1.1 scw
1650 1.15 dyoung sc = device_lookup_private(&utoppy_cd, UTOPPYUNIT(dev));
1651 1.1 scw
1652 1.1 scw if (sc->sc_dying)
1653 1.24.4.5 skrll return EIO;
1654 1.1 scw
1655 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: cmd 0x%08lx, state '%s'\n",
1656 1.15 dyoung device_xname(sc->sc_dev), cmd, utoppy_state_string(sc->sc_state)));
1657 1.1 scw
1658 1.1 scw if (sc->sc_state != UTOPPY_STATE_IDLE && cmd != UTOPPYIOCANCEL) {
1659 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: still busy.\n",
1660 1.15 dyoung device_xname(sc->sc_dev)));
1661 1.24.4.5 skrll return EBUSY;
1662 1.1 scw }
1663 1.1 scw
1664 1.1 scw sc->sc_refcnt++;
1665 1.1 scw
1666 1.1 scw switch (cmd) {
1667 1.1 scw case UTOPPYIOTURBO:
1668 1.1 scw err = 0;
1669 1.1 scw sc->sc_turbo_mode = *((int *)data) ? 1 : 0;
1670 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOTURBO: "
1671 1.15 dyoung "%s\n", device_xname(sc->sc_dev), sc->sc_turbo_mode ? "On" :
1672 1.1 scw "Off"));
1673 1.1 scw break;
1674 1.1 scw
1675 1.1 scw case UTOPPYIOCANCEL:
1676 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOCANCEL\n",
1677 1.15 dyoung device_xname(sc->sc_dev)));
1678 1.1 scw err = utoppy_cancel(sc);
1679 1.1 scw break;
1680 1.1 scw
1681 1.1 scw case UTOPPYIOREBOOT:
1682 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREBOOT\n",
1683 1.15 dyoung device_xname(sc->sc_dev)));
1684 1.1 scw UTOPPY_OUT_INIT(sc);
1685 1.1 scw err = utoppy_command(sc, UTOPPY_CMD_RESET, UTOPPY_LONG_TIMEOUT,
1686 1.1 scw &resp);
1687 1.1 scw if (err)
1688 1.1 scw break;
1689 1.1 scw
1690 1.1 scw if (resp != UTOPPY_RESP_SUCCESS)
1691 1.1 scw err = EIO;
1692 1.1 scw break;
1693 1.1 scw
1694 1.1 scw case UTOPPYIOSTATS:
1695 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOSTATS\n",
1696 1.15 dyoung device_xname(sc->sc_dev)));
1697 1.1 scw err = utoppy_stats(sc, (struct utoppy_stats *)data);
1698 1.1 scw break;
1699 1.1 scw
1700 1.1 scw case UTOPPYIORENAME:
1701 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIORENAME\n",
1702 1.15 dyoung device_xname(sc->sc_dev)));
1703 1.1 scw ur = (struct utoppy_rename *)data;
1704 1.1 scw UTOPPY_OUT_INIT(sc);
1705 1.1 scw
1706 1.1 scw if ((err = utoppy_add_path(sc, ur->ur_old_path, 1)) != 0)
1707 1.1 scw break;
1708 1.1 scw if ((err = utoppy_add_path(sc, ur->ur_new_path, 1)) != 0)
1709 1.1 scw break;
1710 1.1 scw
1711 1.1 scw err = utoppy_command(sc, UTOPPY_CMD_RENAME, UTOPPY_LONG_TIMEOUT,
1712 1.1 scw &resp);
1713 1.1 scw if (err)
1714 1.1 scw break;
1715 1.1 scw
1716 1.1 scw if (resp != UTOPPY_RESP_SUCCESS)
1717 1.1 scw err = EIO;
1718 1.1 scw break;
1719 1.1 scw
1720 1.1 scw case UTOPPYIOMKDIR:
1721 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOMKDIR\n",
1722 1.15 dyoung device_xname(sc->sc_dev)));
1723 1.1 scw UTOPPY_OUT_INIT(sc);
1724 1.1 scw err = utoppy_add_path(sc, *((const char **)data), 1);
1725 1.1 scw if (err)
1726 1.1 scw break;
1727 1.1 scw
1728 1.1 scw err = utoppy_command(sc, UTOPPY_CMD_MKDIR, UTOPPY_LONG_TIMEOUT,
1729 1.1 scw &resp);
1730 1.1 scw if (err)
1731 1.1 scw break;
1732 1.1 scw
1733 1.1 scw if (resp != UTOPPY_RESP_SUCCESS)
1734 1.1 scw err = EIO;
1735 1.1 scw break;
1736 1.1 scw
1737 1.1 scw case UTOPPYIODELETE:
1738 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIODELETE\n",
1739 1.15 dyoung device_xname(sc->sc_dev)));
1740 1.1 scw UTOPPY_OUT_INIT(sc);
1741 1.1 scw err = utoppy_add_path(sc, *((const char **)data), 0);
1742 1.1 scw if (err)
1743 1.1 scw break;
1744 1.1 scw
1745 1.1 scw err = utoppy_command(sc, UTOPPY_CMD_DELETE, UTOPPY_LONG_TIMEOUT,
1746 1.1 scw &resp);
1747 1.1 scw if (err)
1748 1.1 scw break;
1749 1.1 scw
1750 1.1 scw if (resp != UTOPPY_RESP_SUCCESS)
1751 1.1 scw err = EIO;
1752 1.1 scw break;
1753 1.1 scw
1754 1.1 scw case UTOPPYIOREADDIR:
1755 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREADDIR\n",
1756 1.15 dyoung device_xname(sc->sc_dev)));
1757 1.1 scw UTOPPY_OUT_INIT(sc);
1758 1.1 scw err = utoppy_add_path(sc, *((const char **)data), 0);
1759 1.1 scw if (err) {
1760 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
1761 1.1 scw "utoppy_add_path() returned %d\n",
1762 1.15 dyoung device_xname(sc->sc_dev), err));
1763 1.1 scw break;
1764 1.1 scw }
1765 1.1 scw
1766 1.1 scw err = utoppy_send_packet(sc, UTOPPY_CMD_READDIR,
1767 1.1 scw UTOPPY_LONG_TIMEOUT);
1768 1.1 scw if (err != 0) {
1769 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
1770 1.1 scw "UTOPPY_CMD_READDIR returned %d\n",
1771 1.15 dyoung device_xname(sc->sc_dev), err));
1772 1.1 scw break;
1773 1.1 scw }
1774 1.1 scw
1775 1.1 scw err = utoppy_readdir_next(sc);
1776 1.1 scw if (err) {
1777 1.1 scw DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
1778 1.1 scw "utoppy_readdir_next() returned %d\n",
1779 1.15 dyoung device_xname(sc->sc_dev), err));
1780 1.1 scw }
1781 1.1 scw break;
1782 1.1 scw
1783 1.1 scw case UTOPPYIOREADFILE:
1784 1.1 scw urf = (struct utoppy_readfile *)data;
1785 1.1 scw
1786 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOREADFILE "
1787 1.15 dyoung "%s, offset %lld\n", device_xname(sc->sc_dev), urf->ur_path,
1788 1.1 scw urf->ur_offset));
1789 1.1 scw
1790 1.1 scw if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0)
1791 1.1 scw break;
1792 1.1 scw
1793 1.1 scw UTOPPY_OUT_INIT(sc);
1794 1.1 scw utoppy_add_8(sc, UTOPPY_FILE_READ);
1795 1.1 scw
1796 1.1 scw if ((err = utoppy_add_path(sc, urf->ur_path, 1)) != 0)
1797 1.1 scw break;
1798 1.1 scw
1799 1.1 scw utoppy_add_64(sc, urf->ur_offset);
1800 1.1 scw
1801 1.1 scw sc->sc_state = UTOPPY_STATE_READFILE;
1802 1.1 scw sc->sc_in_offset = 0;
1803 1.1 scw
1804 1.1 scw err = utoppy_send_packet(sc, UTOPPY_CMD_FILE,
1805 1.1 scw UTOPPY_LONG_TIMEOUT);
1806 1.1 scw if (err == 0)
1807 1.1 scw err = utoppy_readfile_next(sc);
1808 1.1 scw break;
1809 1.1 scw
1810 1.1 scw case UTOPPYIOWRITEFILE:
1811 1.1 scw uw = (struct utoppy_writefile *)data;
1812 1.1 scw
1813 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOWRITEFILE "
1814 1.15 dyoung "%s, size %lld, offset %lld\n", device_xname(sc->sc_dev),
1815 1.1 scw uw->uw_path, uw->uw_size, uw->uw_offset));
1816 1.1 scw
1817 1.1 scw if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0)
1818 1.1 scw break;
1819 1.1 scw
1820 1.1 scw UTOPPY_OUT_INIT(sc);
1821 1.1 scw utoppy_add_8(sc, UTOPPY_FILE_WRITE);
1822 1.1 scw uwfp = utoppy_current_ptr(sc->sc_out_data);
1823 1.1 scw
1824 1.1 scw if ((err = utoppy_add_path(sc, uw->uw_path, 1)) != 0) {
1825 1.1 scw DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: add_path() "
1826 1.15 dyoung "returned %d\n", device_xname(sc->sc_dev), err));
1827 1.1 scw break;
1828 1.1 scw }
1829 1.1 scw
1830 1.1 scw strncpy(uwf, &uwfp[2], sizeof(uwf));
1831 1.1 scw utoppy_add_64(sc, uw->uw_offset);
1832 1.1 scw
1833 1.1 scw err = utoppy_command(sc, UTOPPY_CMD_FILE, UTOPPY_LONG_TIMEOUT,
1834 1.1 scw &resp);
1835 1.1 scw if (err) {
1836 1.1 scw DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
1837 1.1 scw "utoppy_command(UTOPPY_CMD_FILE) returned "
1838 1.15 dyoung "%d\n", device_xname(sc->sc_dev), err));
1839 1.1 scw break;
1840 1.1 scw }
1841 1.1 scw if (resp != UTOPPY_RESP_SUCCESS) {
1842 1.1 scw DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
1843 1.1 scw "utoppy_command(UTOPPY_CMD_FILE) returned "
1844 1.15 dyoung "bad response 0x%x\n", device_xname(sc->sc_dev),
1845 1.1 scw resp));
1846 1.1 scw err = EIO;
1847 1.1 scw break;
1848 1.1 scw }
1849 1.1 scw
1850 1.1 scw UTOPPY_OUT_INIT(sc);
1851 1.1 scw utoppy_timestamp_encode(sc, uw->uw_mtime);
1852 1.1 scw utoppy_add_8(sc, UTOPPY_FTYPE_FILE);
1853 1.1 scw utoppy_add_64(sc, uw->uw_size);
1854 1.1 scw utoppy_add_string(sc, uwf, sizeof(uwf));
1855 1.1 scw utoppy_add_32(sc, 0);
1856 1.1 scw
1857 1.1 scw err = utoppy_command(sc, UTOPPY_RESP_FILE_HEADER,
1858 1.1 scw UTOPPY_LONG_TIMEOUT, &resp);
1859 1.1 scw if (err) {
1860 1.1 scw DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
1861 1.1 scw "utoppy_command(UTOPPY_RESP_FILE_HEADER) "
1862 1.15 dyoung "returned %d\n", device_xname(sc->sc_dev), err));
1863 1.1 scw break;
1864 1.1 scw }
1865 1.1 scw if (resp != UTOPPY_RESP_SUCCESS) {
1866 1.1 scw DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
1867 1.1 scw "utoppy_command(UTOPPY_RESP_FILE_HEADER) "
1868 1.1 scw "returned bad response 0x%x\n",
1869 1.15 dyoung device_xname(sc->sc_dev), resp));
1870 1.1 scw err = EIO;
1871 1.1 scw break;
1872 1.1 scw }
1873 1.1 scw
1874 1.1 scw sc->sc_wr_offset = uw->uw_offset;
1875 1.1 scw sc->sc_wr_size = uw->uw_size;
1876 1.1 scw sc->sc_state = UTOPPY_STATE_WRITEFILE;
1877 1.1 scw
1878 1.1 scw DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: Changing state to "
1879 1.1 scw "%s. wr_offset %lld, wr_size %lld\n",
1880 1.15 dyoung device_xname(sc->sc_dev), utoppy_state_string(sc->sc_state),
1881 1.1 scw sc->sc_wr_offset, sc->sc_wr_size));
1882 1.1 scw break;
1883 1.1 scw
1884 1.1 scw default:
1885 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: Invalid cmd\n",
1886 1.15 dyoung device_xname(sc->sc_dev)));
1887 1.1 scw err = ENODEV;
1888 1.1 scw break;
1889 1.1 scw }
1890 1.1 scw
1891 1.1 scw DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: done. err %d, state '%s'\n",
1892 1.15 dyoung device_xname(sc->sc_dev), err, utoppy_state_string(sc->sc_state)));
1893 1.1 scw
1894 1.1 scw if (err)
1895 1.1 scw utoppy_cancel(sc);
1896 1.1 scw
1897 1.1 scw if (--sc->sc_refcnt < 0)
1898 1.18 mrg usb_detach_wakeupold(sc->sc_dev);
1899 1.1 scw
1900 1.24.4.5 skrll return err;
1901 1.1 scw }
1902