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