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