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