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