utoppy.c revision 1.5.12.2 1 1.5.12.2 yamt /* $NetBSD: utoppy.c,v 1.5.12.2 2006/06/21 15:07:45 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.2 yamt __KERNEL_RCSID(0, "$NetBSD: utoppy.c,v 1.5.12.2 2006/06/21 15:07:45 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.2 yamt nostop, notty, nopoll, nommap, nokqfilter,
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.2 yamt utoppy_bulk_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
515 1.5.12.2 yamt usbd_status status)
516 1.5.12.2 yamt {
517 1.5.12.2 yamt
518 1.5.12.2 yamt wakeup(xfer);
519 1.5.12.2 yamt }
520 1.5.12.2 yamt
521 1.5.12.2 yamt static usbd_status
522 1.5.12.2 yamt utoppy_bulk_transfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
523 1.5.12.2 yamt u_int16_t flags, u_int32_t timeout, void *buf, u_int32_t *size,
524 1.5.12.2 yamt const char *lbl)
525 1.5.12.2 yamt {
526 1.5.12.2 yamt usbd_status err;
527 1.5.12.2 yamt int s, error;
528 1.5.12.2 yamt
529 1.5.12.2 yamt usbd_setup_xfer(xfer, pipe, 0, buf, *size, flags, timeout,
530 1.5.12.2 yamt utoppy_bulk_transfer_cb);
531 1.5.12.2 yamt s = splusb();
532 1.5.12.2 yamt err = usbd_transfer(xfer);
533 1.5.12.2 yamt if (err != USBD_IN_PROGRESS) {
534 1.5.12.2 yamt splx(s);
535 1.5.12.2 yamt return (err);
536 1.5.12.2 yamt }
537 1.5.12.2 yamt error = tsleep((caddr_t)xfer, PZERO, lbl, 0);
538 1.5.12.2 yamt splx(s);
539 1.5.12.2 yamt if (error) {
540 1.5.12.2 yamt usbd_abort_pipe(pipe);
541 1.5.12.2 yamt return (USBD_INTERRUPTED);
542 1.5.12.2 yamt }
543 1.5.12.2 yamt usbd_get_xfer_status(xfer, NULL, NULL, size, &err);
544 1.5.12.2 yamt return (err);
545 1.5.12.2 yamt }
546 1.5.12.2 yamt
547 1.5.12.2 yamt static int
548 1.5.12.2 yamt utoppy_send_packet(struct utoppy_softc *sc, uint16_t cmd, uint32_t timeout)
549 1.5.12.2 yamt {
550 1.5.12.2 yamt struct utoppy_header *h;
551 1.5.12.2 yamt usbd_status err;
552 1.5.12.2 yamt uint32_t len;
553 1.5.12.2 yamt uint16_t dlen, crc;
554 1.5.12.2 yamt uint8_t *data, *e, t1, t2;
555 1.5.12.2 yamt
556 1.5.12.2 yamt h = sc->sc_out_data;
557 1.5.12.2 yamt
558 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: cmd 0x%04x, "
559 1.5.12.2 yamt "len %d\n", USBDEVNAME(sc->sc_dev), (u_int)cmd, h->h_len));
560 1.5.12.2 yamt
561 1.5.12.2 yamt dlen = h->h_len;
562 1.5.12.2 yamt len = dlen + UTOPPY_HEADER_SIZE;
563 1.5.12.2 yamt
564 1.5.12.2 yamt if (len & 1)
565 1.5.12.2 yamt len++;
566 1.5.12.2 yamt if ((len % 64) == 0)
567 1.5.12.2 yamt len += 2;
568 1.5.12.2 yamt
569 1.5.12.2 yamt if (len >= UTOPPY_BSIZE) {
570 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: "
571 1.5.12.2 yamt "packet too big (%d)\n", USBDEVNAME(sc->sc_dev), (int)len));
572 1.5.12.2 yamt return (EINVAL);
573 1.5.12.2 yamt }
574 1.5.12.2 yamt
575 1.5.12.2 yamt h->h_len = htole16(dlen + UTOPPY_HEADER_SIZE);
576 1.5.12.2 yamt h->h_cmd2 = 0;
577 1.5.12.2 yamt h->h_cmd = htole16(cmd);
578 1.5.12.2 yamt
579 1.5.12.2 yamt /* The command word is part of the CRC */
580 1.5.12.2 yamt crc = UTOPPY_CRC16(0, 0);
581 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, 0);
582 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, cmd >> 8);
583 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, cmd);
584 1.5.12.2 yamt
585 1.5.12.2 yamt /*
586 1.5.12.2 yamt * If there is data following the header, calculate the CRC and
587 1.5.12.2 yamt * byte-swap as we go.
588 1.5.12.2 yamt */
589 1.5.12.2 yamt if (dlen) {
590 1.5.12.2 yamt data = h->h_data;
591 1.5.12.2 yamt e = data + (dlen & ~1);
592 1.5.12.2 yamt
593 1.5.12.2 yamt do {
594 1.5.12.2 yamt t1 = data[0];
595 1.5.12.2 yamt t2 = data[1];
596 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, t1);
597 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, t2);
598 1.5.12.2 yamt *data++ = t2;
599 1.5.12.2 yamt *data++ = t1;
600 1.5.12.2 yamt } while (data < e);
601 1.5.12.2 yamt
602 1.5.12.2 yamt if (dlen & 1) {
603 1.5.12.2 yamt t1 = data[0];
604 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, t1);
605 1.5.12.2 yamt data[1] = t1;
606 1.5.12.2 yamt }
607 1.5.12.2 yamt }
608 1.5.12.2 yamt
609 1.5.12.2 yamt h->h_crc = htole16(crc);
610 1.5.12.2 yamt data = sc->sc_out_data;
611 1.5.12.2 yamt
612 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: total len "
613 1.5.12.2 yamt "%d...\n", USBDEVNAME(sc->sc_dev), (int)len));
614 1.5.12.2 yamt DDUMP_PACKET(data, len);
615 1.5.12.2 yamt
616 1.5.12.2 yamt do {
617 1.5.12.2 yamt uint32_t thislen;
618 1.5.12.2 yamt
619 1.5.12.2 yamt thislen = min(len, UTOPPY_FRAG_SIZE);
620 1.5.12.2 yamt
621 1.5.12.2 yamt memcpy(sc->sc_out_buf, data, thislen);
622 1.5.12.2 yamt
623 1.5.12.2 yamt err = utoppy_bulk_transfer(sc->sc_out_xfer, sc->sc_out_pipe,
624 1.5.12.2 yamt USBD_NO_COPY, timeout, sc->sc_out_buf, &thislen,
625 1.5.12.2 yamt "utoppytx");
626 1.5.12.2 yamt
627 1.5.12.2 yamt if (thislen != min(len, UTOPPY_FRAG_SIZE)) {
628 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: "
629 1.5.12.2 yamt "utoppy_send_packet: sent %ld, err %d\n",
630 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), (u_long)thislen, err));
631 1.5.12.2 yamt }
632 1.5.12.2 yamt
633 1.5.12.2 yamt if (err == 0) {
634 1.5.12.2 yamt len -= thislen;
635 1.5.12.2 yamt data += thislen;
636 1.5.12.2 yamt }
637 1.5.12.2 yamt } while (err == 0 && len);
638 1.5.12.2 yamt
639 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_SEND_PACKET, ("%s: utoppy_send_packet: "
640 1.5.12.2 yamt "usbd_bulk_transfer() returned %d.\n", USBDEVNAME(sc->sc_dev),err));
641 1.5.12.2 yamt
642 1.5.12.2 yamt return (err ? utoppy_usbd_status2errno(err) : 0);
643 1.5.12.2 yamt }
644 1.5.12.2 yamt
645 1.5.12.2 yamt static int
646 1.5.12.2 yamt utoppy_recv_packet(struct utoppy_softc *sc, uint16_t *respp, uint32_t timeout)
647 1.5.12.2 yamt {
648 1.5.12.2 yamt struct utoppy_header *h;
649 1.5.12.2 yamt usbd_status err;
650 1.5.12.2 yamt uint32_t len, thislen, requested, bytesleft;
651 1.5.12.2 yamt uint16_t crc;
652 1.5.12.2 yamt uint8_t *data, *e, t1, t2;
653 1.5.12.2 yamt
654 1.5.12.2 yamt data = sc->sc_in_data;
655 1.5.12.2 yamt len = 0;
656 1.5.12.2 yamt bytesleft = UTOPPY_BSIZE;
657 1.5.12.2 yamt
658 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: ...\n",
659 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
660 1.5.12.2 yamt
661 1.5.12.2 yamt do {
662 1.5.12.2 yamt requested = thislen = min(bytesleft, UTOPPY_FRAG_SIZE);
663 1.5.12.2 yamt
664 1.5.12.2 yamt err = utoppy_bulk_transfer(sc->sc_in_xfer, sc->sc_in_pipe,
665 1.5.12.2 yamt USBD_NO_COPY | USBD_SHORT_XFER_OK, timeout, sc->sc_in_buf,
666 1.5.12.2 yamt &thislen, "utoppyrx");
667 1.5.12.2 yamt
668 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: "
669 1.5.12.2 yamt "usbd_bulk_transfer() returned %d, thislen %d, data %p\n",
670 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err, (u_int)thislen, data));
671 1.5.12.2 yamt
672 1.5.12.2 yamt if (err == 0) {
673 1.5.12.2 yamt memcpy(data, sc->sc_in_buf, thislen);
674 1.5.12.2 yamt DDUMP_PACKET(data, thislen);
675 1.5.12.2 yamt len += thislen;
676 1.5.12.2 yamt bytesleft -= thislen;
677 1.5.12.2 yamt data += thislen;
678 1.5.12.2 yamt }
679 1.5.12.2 yamt } while (err == 0 && bytesleft && thislen == requested);
680 1.5.12.2 yamt
681 1.5.12.2 yamt if (err)
682 1.5.12.2 yamt return (utoppy_usbd_status2errno(err));
683 1.5.12.2 yamt
684 1.5.12.2 yamt h = sc->sc_in_data;
685 1.5.12.2 yamt
686 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: received %d "
687 1.5.12.2 yamt "bytes in total to %p\n", USBDEVNAME(sc->sc_dev), (u_int)len, h));
688 1.5.12.2 yamt DDUMP_PACKET(h, len);
689 1.5.12.2 yamt
690 1.5.12.2 yamt if (len < UTOPPY_HEADER_SIZE || len < (uint32_t)le16toh(h->h_len)) {
691 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: bad "
692 1.5.12.2 yamt " length (len %d, h_len %d)\n", USBDEVNAME(sc->sc_dev),
693 1.5.12.2 yamt (int)len, le16toh(h->h_len)));
694 1.5.12.2 yamt return (EIO);
695 1.5.12.2 yamt }
696 1.5.12.2 yamt
697 1.5.12.2 yamt len = h->h_len = le16toh(h->h_len);
698 1.5.12.2 yamt h->h_crc = le16toh(h->h_crc);
699 1.5.12.2 yamt *respp = h->h_cmd = le16toh(h->h_cmd);
700 1.5.12.2 yamt h->h_cmd2 = le16toh(h->h_cmd2);
701 1.5.12.2 yamt
702 1.5.12.2 yamt /*
703 1.5.12.2 yamt * To maximise data throughput when transferring files, acknowledge
704 1.5.12.2 yamt * data blocks as soon as we receive them. If we detect an error
705 1.5.12.2 yamt * later on, we can always cancel.
706 1.5.12.2 yamt */
707 1.5.12.2 yamt if (*respp == UTOPPY_RESP_FILE_DATA) {
708 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: "
709 1.5.12.2 yamt "ACKing file data\n", USBDEVNAME(sc->sc_dev)));
710 1.5.12.2 yamt
711 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
712 1.5.12.2 yamt err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
713 1.5.12.2 yamt UTOPPY_SHORT_TIMEOUT);
714 1.5.12.2 yamt if (err) {
715 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: "
716 1.5.12.2 yamt "utoppy_recv_packet: failed to ACK file data: %d\n",
717 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err));
718 1.5.12.2 yamt return (err);
719 1.5.12.2 yamt }
720 1.5.12.2 yamt }
721 1.5.12.2 yamt
722 1.5.12.2 yamt /* The command word is part of the CRC */
723 1.5.12.2 yamt crc = UTOPPY_CRC16(0, h->h_cmd2 >> 8);
724 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, h->h_cmd2);
725 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, h->h_cmd >> 8);
726 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, h->h_cmd);
727 1.5.12.2 yamt
728 1.5.12.2 yamt /*
729 1.5.12.2 yamt * Extract any payload, byte-swapping and calculating the CRC16
730 1.5.12.2 yamt * as we go.
731 1.5.12.2 yamt */
732 1.5.12.2 yamt if (len > UTOPPY_HEADER_SIZE) {
733 1.5.12.2 yamt data = h->h_data;
734 1.5.12.2 yamt e = data + ((len & ~1) - UTOPPY_HEADER_SIZE);
735 1.5.12.2 yamt
736 1.5.12.2 yamt while (data < e) {
737 1.5.12.2 yamt t1 = data[0];
738 1.5.12.2 yamt t2 = data[1];
739 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, t2);
740 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, t1);
741 1.5.12.2 yamt *data++ = t2;
742 1.5.12.2 yamt *data++ = t1;
743 1.5.12.2 yamt }
744 1.5.12.2 yamt
745 1.5.12.2 yamt if (len & 1) {
746 1.5.12.2 yamt t1 = data[1];
747 1.5.12.2 yamt crc = UTOPPY_CRC16(crc, t1);
748 1.5.12.2 yamt *data = t1;
749 1.5.12.2 yamt }
750 1.5.12.2 yamt }
751 1.5.12.2 yamt
752 1.5.12.2 yamt sc->sc_in_len = (size_t) len - UTOPPY_HEADER_SIZE;
753 1.5.12.2 yamt sc->sc_in_offset = 0;
754 1.5.12.2 yamt
755 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_RECV_PACKET, ("%s: utoppy_recv_packet: len %d, "
756 1.5.12.2 yamt "crc 0x%04x, hdrcrc 0x%04x\n", USBDEVNAME(sc->sc_dev),
757 1.5.12.2 yamt (int)len, crc, h->h_crc));
758 1.5.12.2 yamt DDUMP_PACKET(h, len);
759 1.5.12.2 yamt
760 1.5.12.2 yamt return ((crc == h->h_crc) ? 0 : EBADMSG);
761 1.5.12.2 yamt }
762 1.5.12.2 yamt
763 1.5.12.2 yamt static __inline void *
764 1.5.12.2 yamt utoppy_current_ptr(void *b)
765 1.5.12.2 yamt {
766 1.5.12.2 yamt struct utoppy_header *h = b;
767 1.5.12.2 yamt
768 1.5.12.2 yamt return (&h->h_data[h->h_len]);
769 1.5.12.2 yamt }
770 1.5.12.2 yamt
771 1.5.12.2 yamt static __inline void
772 1.5.12.2 yamt utoppy_advance_ptr(void *b, size_t len)
773 1.5.12.2 yamt {
774 1.5.12.2 yamt struct utoppy_header *h = b;
775 1.5.12.2 yamt
776 1.5.12.2 yamt h->h_len += len;
777 1.5.12.2 yamt }
778 1.5.12.2 yamt
779 1.5.12.2 yamt static __inline void
780 1.5.12.2 yamt utoppy_add_8(struct utoppy_softc *sc, uint8_t v)
781 1.5.12.2 yamt {
782 1.5.12.2 yamt struct utoppy_header *h = sc->sc_out_data;
783 1.5.12.2 yamt uint8_t *p;
784 1.5.12.2 yamt
785 1.5.12.2 yamt p = utoppy_current_ptr(h);
786 1.5.12.2 yamt *p = v;
787 1.5.12.2 yamt utoppy_advance_ptr(h, sizeof(v));
788 1.5.12.2 yamt }
789 1.5.12.2 yamt
790 1.5.12.2 yamt static __inline void
791 1.5.12.2 yamt utoppy_add_16(struct utoppy_softc *sc, uint16_t v)
792 1.5.12.2 yamt {
793 1.5.12.2 yamt struct utoppy_header *h = sc->sc_out_data;
794 1.5.12.2 yamt uint8_t *p;
795 1.5.12.2 yamt
796 1.5.12.2 yamt p = utoppy_current_ptr(h);
797 1.5.12.2 yamt *p++ = (uint8_t)(v >> 8);
798 1.5.12.2 yamt *p = (uint8_t)v;
799 1.5.12.2 yamt utoppy_advance_ptr(h, sizeof(v));
800 1.5.12.2 yamt }
801 1.5.12.2 yamt
802 1.5.12.2 yamt static __inline void
803 1.5.12.2 yamt utoppy_add_32(struct utoppy_softc *sc, uint32_t v)
804 1.5.12.2 yamt {
805 1.5.12.2 yamt struct utoppy_header *h = sc->sc_out_data;
806 1.5.12.2 yamt uint8_t *p;
807 1.5.12.2 yamt
808 1.5.12.2 yamt p = utoppy_current_ptr(h);
809 1.5.12.2 yamt *p++ = (uint8_t)(v >> 24);
810 1.5.12.2 yamt *p++ = (uint8_t)(v >> 16);
811 1.5.12.2 yamt *p++ = (uint8_t)(v >> 8);
812 1.5.12.2 yamt *p = (uint8_t)v;
813 1.5.12.2 yamt utoppy_advance_ptr(h, sizeof(v));
814 1.5.12.2 yamt }
815 1.5.12.2 yamt
816 1.5.12.2 yamt static __inline void
817 1.5.12.2 yamt utoppy_add_64(struct utoppy_softc *sc, uint64_t v)
818 1.5.12.2 yamt {
819 1.5.12.2 yamt struct utoppy_header *h = sc->sc_out_data;
820 1.5.12.2 yamt uint8_t *p;
821 1.5.12.2 yamt
822 1.5.12.2 yamt p = utoppy_current_ptr(h);
823 1.5.12.2 yamt *p++ = (uint8_t)(v >> 56);
824 1.5.12.2 yamt *p++ = (uint8_t)(v >> 48);
825 1.5.12.2 yamt *p++ = (uint8_t)(v >> 40);
826 1.5.12.2 yamt *p++ = (uint8_t)(v >> 32);
827 1.5.12.2 yamt *p++ = (uint8_t)(v >> 24);
828 1.5.12.2 yamt *p++ = (uint8_t)(v >> 16);
829 1.5.12.2 yamt *p++ = (uint8_t)(v >> 8);
830 1.5.12.2 yamt *p = (uint8_t)v;
831 1.5.12.2 yamt utoppy_advance_ptr(h, sizeof(v));
832 1.5.12.2 yamt }
833 1.5.12.2 yamt
834 1.5.12.2 yamt static __inline void
835 1.5.12.2 yamt utoppy_add_string(struct utoppy_softc *sc, const char *str, size_t len)
836 1.5.12.2 yamt {
837 1.5.12.2 yamt struct utoppy_header *h = sc->sc_out_data;
838 1.5.12.2 yamt char *p;
839 1.5.12.2 yamt
840 1.5.12.2 yamt p = utoppy_current_ptr(h);
841 1.5.12.2 yamt memset(p, 0, len);
842 1.5.12.2 yamt strncpy(p, str, len);
843 1.5.12.2 yamt utoppy_advance_ptr(h, len);
844 1.5.12.2 yamt }
845 1.5.12.2 yamt
846 1.5.12.2 yamt static int
847 1.5.12.2 yamt utoppy_add_path(struct utoppy_softc *sc, const char *path, int putlen)
848 1.5.12.2 yamt {
849 1.5.12.2 yamt struct utoppy_header *h = sc->sc_out_data;
850 1.5.12.2 yamt uint8_t *p, *str, *s;
851 1.5.12.2 yamt size_t len;
852 1.5.12.2 yamt int err;
853 1.5.12.2 yamt
854 1.5.12.2 yamt p = utoppy_current_ptr(h);
855 1.5.12.2 yamt
856 1.5.12.2 yamt str = putlen ? (p + sizeof(uint16_t)) : p;
857 1.5.12.2 yamt
858 1.5.12.2 yamt err = copyinstr(path, str, UTOPPY_MAX_FILENAME_LEN, &len);
859 1.5.12.2 yamt
860 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: err %d, len %d\n",
861 1.5.12.2 yamt err, (int)len));
862 1.5.12.2 yamt
863 1.5.12.2 yamt if (err)
864 1.5.12.2 yamt return (err);
865 1.5.12.2 yamt
866 1.5.12.2 yamt if (len < 2)
867 1.5.12.2 yamt return (EINVAL);
868 1.5.12.2 yamt
869 1.5.12.2 yamt /*
870 1.5.12.2 yamt * copyinstr(9) has already copied the terminating NUL character,
871 1.5.12.2 yamt * but we append another one in case we have to pad the length
872 1.5.12.2 yamt * later on.
873 1.5.12.2 yamt */
874 1.5.12.2 yamt str[len] = '\0';
875 1.5.12.2 yamt
876 1.5.12.2 yamt /*
877 1.5.12.2 yamt * The Toppy uses backslash as the directory separator, so convert
878 1.5.12.2 yamt * all forward slashes.
879 1.5.12.2 yamt */
880 1.5.12.2 yamt for (s = &str[len - 2]; s >= str; s--)
881 1.5.12.2 yamt if (*s == '/')
882 1.5.12.2 yamt *s = '\\';
883 1.5.12.2 yamt
884 1.5.12.2 yamt if ((len + h->h_len) & 1)
885 1.5.12.2 yamt len++;
886 1.5.12.2 yamt
887 1.5.12.2 yamt if (putlen)
888 1.5.12.2 yamt utoppy_add_16(sc, len);
889 1.5.12.2 yamt
890 1.5.12.2 yamt utoppy_advance_ptr(h, len);
891 1.5.12.2 yamt
892 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_ADDPATH, ("utoppy_add_path: final len %d\n",
893 1.5.12.2 yamt (u_int)len));
894 1.5.12.2 yamt
895 1.5.12.2 yamt return (0);
896 1.5.12.2 yamt }
897 1.5.12.2 yamt
898 1.5.12.2 yamt static __inline int
899 1.5.12.2 yamt utoppy_get_8(struct utoppy_softc *sc, uint8_t *vp)
900 1.5.12.2 yamt {
901 1.5.12.2 yamt uint8_t *p;
902 1.5.12.2 yamt
903 1.5.12.2 yamt if (sc->sc_in_len < sizeof(*vp))
904 1.5.12.2 yamt return (1);
905 1.5.12.2 yamt
906 1.5.12.2 yamt p = UTOPPY_IN_DATA(sc);
907 1.5.12.2 yamt *vp = *p;
908 1.5.12.2 yamt sc->sc_in_offset += sizeof(*vp);
909 1.5.12.2 yamt sc->sc_in_len -= sizeof(*vp);
910 1.5.12.2 yamt return (0);
911 1.5.12.2 yamt }
912 1.5.12.2 yamt
913 1.5.12.2 yamt static __inline int
914 1.5.12.2 yamt utoppy_get_16(struct utoppy_softc *sc, uint16_t *vp)
915 1.5.12.2 yamt {
916 1.5.12.2 yamt uint16_t v;
917 1.5.12.2 yamt uint8_t *p;
918 1.5.12.2 yamt
919 1.5.12.2 yamt if (sc->sc_in_len < sizeof(v))
920 1.5.12.2 yamt return (1);
921 1.5.12.2 yamt
922 1.5.12.2 yamt p = UTOPPY_IN_DATA(sc);
923 1.5.12.2 yamt v = *p++;
924 1.5.12.2 yamt v = (v << 8) | *p;
925 1.5.12.2 yamt *vp = v;
926 1.5.12.2 yamt sc->sc_in_offset += sizeof(v);
927 1.5.12.2 yamt sc->sc_in_len -= sizeof(v);
928 1.5.12.2 yamt return (0);
929 1.5.12.2 yamt }
930 1.5.12.2 yamt
931 1.5.12.2 yamt static __inline int
932 1.5.12.2 yamt utoppy_get_32(struct utoppy_softc *sc, uint32_t *vp)
933 1.5.12.2 yamt {
934 1.5.12.2 yamt uint32_t v;
935 1.5.12.2 yamt uint8_t *p;
936 1.5.12.2 yamt
937 1.5.12.2 yamt if (sc->sc_in_len < sizeof(v))
938 1.5.12.2 yamt return (1);
939 1.5.12.2 yamt
940 1.5.12.2 yamt p = UTOPPY_IN_DATA(sc);
941 1.5.12.2 yamt v = *p++;
942 1.5.12.2 yamt v = (v << 8) | *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 *vp = v;
946 1.5.12.2 yamt sc->sc_in_offset += sizeof(v);
947 1.5.12.2 yamt sc->sc_in_len -= sizeof(v);
948 1.5.12.2 yamt return (0);
949 1.5.12.2 yamt }
950 1.5.12.2 yamt
951 1.5.12.2 yamt static __inline int
952 1.5.12.2 yamt utoppy_get_64(struct utoppy_softc *sc, uint64_t *vp)
953 1.5.12.2 yamt {
954 1.5.12.2 yamt uint64_t v;
955 1.5.12.2 yamt uint8_t *p;
956 1.5.12.2 yamt
957 1.5.12.2 yamt if (sc->sc_in_len < sizeof(v))
958 1.5.12.2 yamt return (1);
959 1.5.12.2 yamt
960 1.5.12.2 yamt p = UTOPPY_IN_DATA(sc);
961 1.5.12.2 yamt v = *p++;
962 1.5.12.2 yamt v = (v << 8) | *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 *vp = v;
970 1.5.12.2 yamt sc->sc_in_offset += sizeof(v);
971 1.5.12.2 yamt sc->sc_in_len -= sizeof(v);
972 1.5.12.2 yamt return (0);
973 1.5.12.2 yamt }
974 1.5.12.2 yamt
975 1.5.12.2 yamt static __inline int
976 1.5.12.2 yamt utoppy_get_string(struct utoppy_softc *sc, char *str, size_t len)
977 1.5.12.2 yamt {
978 1.5.12.2 yamt char *p;
979 1.5.12.2 yamt
980 1.5.12.2 yamt if (sc->sc_in_len < len)
981 1.5.12.2 yamt return (1);
982 1.5.12.2 yamt
983 1.5.12.2 yamt memset(str, 0, len);
984 1.5.12.2 yamt p = UTOPPY_IN_DATA(sc);
985 1.5.12.2 yamt strncpy(str, p, len);
986 1.5.12.2 yamt sc->sc_in_offset += len;
987 1.5.12.2 yamt sc->sc_in_len -= len;
988 1.5.12.2 yamt return (0);
989 1.5.12.2 yamt }
990 1.5.12.2 yamt
991 1.5.12.2 yamt static int
992 1.5.12.2 yamt utoppy_command(struct utoppy_softc *sc, uint16_t cmd, int timeout,
993 1.5.12.2 yamt uint16_t *presp)
994 1.5.12.2 yamt {
995 1.5.12.2 yamt int err;
996 1.5.12.2 yamt
997 1.5.12.2 yamt err = utoppy_send_packet(sc, cmd, timeout);
998 1.5.12.2 yamt if (err)
999 1.5.12.2 yamt return (err);
1000 1.5.12.2 yamt
1001 1.5.12.2 yamt err = utoppy_recv_packet(sc, presp, timeout);
1002 1.5.12.2 yamt if (err == EBADMSG) {
1003 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1004 1.5.12.2 yamt utoppy_send_packet(sc, UTOPPY_RESP_ERROR, timeout);
1005 1.5.12.2 yamt }
1006 1.5.12.2 yamt
1007 1.5.12.2 yamt return (err);
1008 1.5.12.2 yamt }
1009 1.5.12.2 yamt
1010 1.5.12.2 yamt static int
1011 1.5.12.2 yamt utoppy_timestamp_decode(struct utoppy_softc *sc, time_t *tp)
1012 1.5.12.2 yamt {
1013 1.5.12.2 yamt uint16_t mjd;
1014 1.5.12.2 yamt uint8_t hour, minute, sec;
1015 1.5.12.2 yamt uint32_t rv;
1016 1.5.12.2 yamt
1017 1.5.12.2 yamt if (utoppy_get_16(sc, &mjd) || utoppy_get_8(sc, &hour) ||
1018 1.5.12.2 yamt utoppy_get_8(sc, &minute) || utoppy_get_8(sc, &sec))
1019 1.5.12.2 yamt return (1);
1020 1.5.12.2 yamt
1021 1.5.12.2 yamt if (mjd == 0xffffu && hour == 0xffu && minute == 0xffu && sec == 0xffu){
1022 1.5.12.2 yamt *tp = 0;
1023 1.5.12.2 yamt return (0);
1024 1.5.12.2 yamt }
1025 1.5.12.2 yamt
1026 1.5.12.2 yamt rv = (mjd < UTOPPY_MJD_1970) ? UTOPPY_MJD_1970 : (uint32_t) mjd;
1027 1.5.12.2 yamt
1028 1.5.12.2 yamt /* Calculate seconds since 1970 */
1029 1.5.12.2 yamt rv = (rv - UTOPPY_MJD_1970) * 60 * 60 * 24;
1030 1.5.12.2 yamt
1031 1.5.12.2 yamt /* Add in the hours, minutes, and seconds */
1032 1.5.12.2 yamt rv += (uint32_t)hour * 60 * 60;
1033 1.5.12.2 yamt rv += (uint32_t)minute * 60;
1034 1.5.12.2 yamt rv += sec;
1035 1.5.12.2 yamt *tp = (time_t)rv;
1036 1.5.12.2 yamt
1037 1.5.12.2 yamt return (0);
1038 1.5.12.2 yamt }
1039 1.5.12.2 yamt
1040 1.5.12.2 yamt static void
1041 1.5.12.2 yamt utoppy_timestamp_encode(struct utoppy_softc *sc, time_t t)
1042 1.5.12.2 yamt {
1043 1.5.12.2 yamt u_int mjd, hour, minute;
1044 1.5.12.2 yamt
1045 1.5.12.2 yamt mjd = t / (60 * 60 * 24);
1046 1.5.12.2 yamt t -= mjd * 60 * 60 * 24;
1047 1.5.12.2 yamt
1048 1.5.12.2 yamt hour = t / (60 * 60);
1049 1.5.12.2 yamt t -= hour * 60 * 60;
1050 1.5.12.2 yamt
1051 1.5.12.2 yamt minute = t / 60;
1052 1.5.12.2 yamt t -= minute * 60;
1053 1.5.12.2 yamt
1054 1.5.12.2 yamt utoppy_add_16(sc, mjd + UTOPPY_MJD_1970);
1055 1.5.12.2 yamt utoppy_add_8(sc, hour);
1056 1.5.12.2 yamt utoppy_add_8(sc, minute);
1057 1.5.12.2 yamt utoppy_add_8(sc, t);
1058 1.5.12.2 yamt }
1059 1.5.12.2 yamt
1060 1.5.12.2 yamt static int
1061 1.5.12.2 yamt utoppy_turbo_mode(struct utoppy_softc *sc, int state)
1062 1.5.12.2 yamt {
1063 1.5.12.2 yamt uint16_t r;
1064 1.5.12.2 yamt int err;
1065 1.5.12.2 yamt
1066 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1067 1.5.12.2 yamt utoppy_add_32(sc, state);
1068 1.5.12.2 yamt
1069 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_CMD_TURBO, UTOPPY_SHORT_TIMEOUT, &r);
1070 1.5.12.2 yamt if (err)
1071 1.5.12.2 yamt return (err);
1072 1.5.12.2 yamt
1073 1.5.12.2 yamt return ((r == UTOPPY_RESP_SUCCESS) ? 0 : EIO);
1074 1.5.12.2 yamt }
1075 1.5.12.2 yamt
1076 1.5.12.2 yamt static int
1077 1.5.12.2 yamt utoppy_check_ready(struct utoppy_softc *sc)
1078 1.5.12.2 yamt {
1079 1.5.12.2 yamt uint16_t r;
1080 1.5.12.2 yamt int err;
1081 1.5.12.2 yamt
1082 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1083 1.5.12.2 yamt
1084 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_CMD_READY, UTOPPY_LONG_TIMEOUT, &r);
1085 1.5.12.2 yamt if (err)
1086 1.5.12.2 yamt return (err);
1087 1.5.12.2 yamt
1088 1.5.12.2 yamt return ((r == UTOPPY_RESP_SUCCESS) ? 0 : EIO);
1089 1.5.12.2 yamt }
1090 1.5.12.2 yamt
1091 1.5.12.2 yamt static int
1092 1.5.12.2 yamt utoppy_cancel(struct utoppy_softc *sc)
1093 1.5.12.2 yamt {
1094 1.5.12.2 yamt uint16_t r;
1095 1.5.12.2 yamt int err, i;
1096 1.5.12.2 yamt
1097 1.5.12.2 yamt /*
1098 1.5.12.2 yamt * Issue the cancel command serveral times. the Toppy doesn't
1099 1.5.12.2 yamt * always respond to the first.
1100 1.5.12.2 yamt */
1101 1.5.12.2 yamt for (i = 0; i < 3; i++) {
1102 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1103 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_CMD_CANCEL,
1104 1.5.12.2 yamt UTOPPY_SHORT_TIMEOUT, &r);
1105 1.5.12.2 yamt if (err == 0 && r == UTOPPY_RESP_SUCCESS)
1106 1.5.12.2 yamt break;
1107 1.5.12.2 yamt err = ETIMEDOUT;
1108 1.5.12.2 yamt }
1109 1.5.12.2 yamt
1110 1.5.12.2 yamt if (err)
1111 1.5.12.2 yamt return (err);
1112 1.5.12.2 yamt
1113 1.5.12.2 yamt /*
1114 1.5.12.2 yamt * Make sure turbo mode is off, otherwise the Toppy will not
1115 1.5.12.2 yamt * respond to remote control input.
1116 1.5.12.2 yamt */
1117 1.5.12.2 yamt (void) utoppy_turbo_mode(sc, 0);
1118 1.5.12.2 yamt
1119 1.5.12.2 yamt sc->sc_state = UTOPPY_STATE_IDLE;
1120 1.5.12.2 yamt return (0);
1121 1.5.12.2 yamt }
1122 1.5.12.2 yamt
1123 1.5.12.2 yamt static int
1124 1.5.12.2 yamt utoppy_stats(struct utoppy_softc *sc, struct utoppy_stats *us)
1125 1.5.12.2 yamt {
1126 1.5.12.2 yamt uint32_t hsize, hfree;
1127 1.5.12.2 yamt uint16_t r;
1128 1.5.12.2 yamt int err;
1129 1.5.12.2 yamt
1130 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1131 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_CMD_STATS, UTOPPY_LONG_TIMEOUT, &r);
1132 1.5.12.2 yamt if (err)
1133 1.5.12.2 yamt return (err);
1134 1.5.12.2 yamt
1135 1.5.12.2 yamt if (r != UTOPPY_RESP_STATS_DATA)
1136 1.5.12.2 yamt return (EIO);
1137 1.5.12.2 yamt
1138 1.5.12.2 yamt if (utoppy_get_32(sc, &hsize) || utoppy_get_32(sc, &hfree))
1139 1.5.12.2 yamt return (EIO);
1140 1.5.12.2 yamt
1141 1.5.12.2 yamt us->us_hdd_size = hsize;
1142 1.5.12.2 yamt us->us_hdd_size *= 1024;
1143 1.5.12.2 yamt us->us_hdd_free = hfree;
1144 1.5.12.2 yamt us->us_hdd_free *= 1024;
1145 1.5.12.2 yamt
1146 1.5.12.2 yamt return (0);
1147 1.5.12.2 yamt }
1148 1.5.12.2 yamt
1149 1.5.12.2 yamt static int
1150 1.5.12.2 yamt utoppy_readdir_next(struct utoppy_softc *sc)
1151 1.5.12.2 yamt {
1152 1.5.12.2 yamt uint16_t resp;
1153 1.5.12.2 yamt int err;
1154 1.5.12.2 yamt
1155 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: running...\n",
1156 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1157 1.5.12.2 yamt
1158 1.5.12.2 yamt /*
1159 1.5.12.2 yamt * Fetch the next READDIR response
1160 1.5.12.2 yamt */
1161 1.5.12.2 yamt err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT);
1162 1.5.12.2 yamt if (err) {
1163 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1164 1.5.12.2 yamt "utoppy_recv_packet() returned %d\n",
1165 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err));
1166 1.5.12.2 yamt if (err == EBADMSG) {
1167 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1168 1.5.12.2 yamt utoppy_send_packet(sc, UTOPPY_RESP_ERROR,
1169 1.5.12.2 yamt UTOPPY_LONG_TIMEOUT);
1170 1.5.12.2 yamt }
1171 1.5.12.2 yamt utoppy_cancel(sc);
1172 1.5.12.2 yamt return (err);
1173 1.5.12.2 yamt }
1174 1.5.12.2 yamt
1175 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1176 1.5.12.2 yamt "utoppy_recv_packet() returned %d, len %ld\n",
1177 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err, (u_long)sc->sc_in_len));
1178 1.5.12.2 yamt
1179 1.5.12.2 yamt switch (resp) {
1180 1.5.12.2 yamt case UTOPPY_RESP_READDIR_DATA:
1181 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1182 1.5.12.2 yamt "UTOPPY_RESP_READDIR_DATA\n", USBDEVNAME(sc->sc_dev)));
1183 1.5.12.2 yamt
1184 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1185 1.5.12.2 yamt err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
1186 1.5.12.2 yamt UTOPPY_LONG_TIMEOUT);
1187 1.5.12.2 yamt if (err) {
1188 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1189 1.5.12.2 yamt "utoppy_send_packet(ACK) returned %d\n",
1190 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err));
1191 1.5.12.2 yamt utoppy_cancel(sc);
1192 1.5.12.2 yamt return (err);
1193 1.5.12.2 yamt }
1194 1.5.12.2 yamt sc->sc_state = UTOPPY_STATE_READDIR;
1195 1.5.12.2 yamt sc->sc_in_offset = 0;
1196 1.5.12.2 yamt break;
1197 1.5.12.2 yamt
1198 1.5.12.2 yamt case UTOPPY_RESP_READDIR_END:
1199 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1200 1.5.12.2 yamt "UTOPPY_RESP_READDIR_END\n", USBDEVNAME(sc->sc_dev)));
1201 1.5.12.2 yamt
1202 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1203 1.5.12.2 yamt utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT);
1204 1.5.12.2 yamt sc->sc_state = UTOPPY_STATE_IDLE;
1205 1.5.12.2 yamt sc->sc_in_len = 0;
1206 1.5.12.2 yamt break;
1207 1.5.12.2 yamt
1208 1.5.12.2 yamt default:
1209 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_next: "
1210 1.5.12.2 yamt "bad response: 0x%x\n", USBDEVNAME(sc->sc_dev), resp));
1211 1.5.12.2 yamt sc->sc_state = UTOPPY_STATE_IDLE;
1212 1.5.12.2 yamt sc->sc_in_len = 0;
1213 1.5.12.2 yamt return (EIO);
1214 1.5.12.2 yamt }
1215 1.5.12.2 yamt
1216 1.5.12.2 yamt return (0);
1217 1.5.12.2 yamt }
1218 1.5.12.2 yamt
1219 1.5.12.2 yamt static size_t
1220 1.5.12.2 yamt utoppy_readdir_decode(struct utoppy_softc *sc, struct utoppy_dirent *ud)
1221 1.5.12.2 yamt {
1222 1.5.12.2 yamt uint8_t ftype;
1223 1.5.12.2 yamt
1224 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: bytes left"
1225 1.5.12.2 yamt " %d\n", USBDEVNAME(sc->sc_dev), (int)sc->sc_in_len));
1226 1.5.12.2 yamt
1227 1.5.12.2 yamt if (utoppy_timestamp_decode(sc, &ud->ud_mtime) ||
1228 1.5.12.2 yamt utoppy_get_8(sc, &ftype) || utoppy_get_64(sc, &ud->ud_size) ||
1229 1.5.12.2 yamt utoppy_get_string(sc, ud->ud_path, UTOPPY_MAX_FILENAME_LEN + 1) ||
1230 1.5.12.2 yamt utoppy_get_32(sc, &ud->ud_attributes)) {
1231 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: no "
1232 1.5.12.2 yamt "more to decode\n", USBDEVNAME(sc->sc_dev)));
1233 1.5.12.2 yamt return (0);
1234 1.5.12.2 yamt }
1235 1.5.12.2 yamt
1236 1.5.12.2 yamt switch (ftype) {
1237 1.5.12.2 yamt case UTOPPY_FTYPE_DIR:
1238 1.5.12.2 yamt ud->ud_type = UTOPPY_DIRENT_DIRECTORY;
1239 1.5.12.2 yamt break;
1240 1.5.12.2 yamt case UTOPPY_FTYPE_FILE:
1241 1.5.12.2 yamt ud->ud_type = UTOPPY_DIRENT_FILE;
1242 1.5.12.2 yamt break;
1243 1.5.12.2 yamt default:
1244 1.5.12.2 yamt ud->ud_type = UTOPPY_DIRENT_UNKNOWN;
1245 1.5.12.2 yamt break;
1246 1.5.12.2 yamt }
1247 1.5.12.2 yamt
1248 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppy_readdir_decode: %s '%s', "
1249 1.5.12.2 yamt "size %lld, time 0x%08lx, attr 0x%08x\n", USBDEVNAME(sc->sc_dev),
1250 1.5.12.2 yamt (ftype == UTOPPY_FTYPE_DIR) ? "DIR" :
1251 1.5.12.2 yamt ((ftype == UTOPPY_FTYPE_FILE) ? "FILE" : "UNKNOWN"), ud->ud_path,
1252 1.5.12.2 yamt ud->ud_size, (u_long)ud->ud_mtime, ud->ud_attributes));
1253 1.5.12.2 yamt
1254 1.5.12.2 yamt return (1);
1255 1.5.12.2 yamt }
1256 1.5.12.2 yamt
1257 1.5.12.2 yamt static int
1258 1.5.12.2 yamt utoppy_readfile_next(struct utoppy_softc *sc)
1259 1.5.12.2 yamt {
1260 1.5.12.2 yamt uint64_t off;
1261 1.5.12.2 yamt uint16_t resp;
1262 1.5.12.2 yamt int err;
1263 1.5.12.2 yamt
1264 1.5.12.2 yamt err = utoppy_recv_packet(sc, &resp, UTOPPY_LONG_TIMEOUT);
1265 1.5.12.2 yamt if (err) {
1266 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1267 1.5.12.2 yamt "utoppy_recv_packet() returned %d\n",
1268 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err));
1269 1.5.12.2 yamt utoppy_cancel(sc);
1270 1.5.12.2 yamt return (err);
1271 1.5.12.2 yamt }
1272 1.5.12.2 yamt
1273 1.5.12.2 yamt switch (resp) {
1274 1.5.12.2 yamt case UTOPPY_RESP_FILE_HEADER:
1275 1.5.12.2 yamt /* ACK it */
1276 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1277 1.5.12.2 yamt err = utoppy_send_packet(sc, UTOPPY_CMD_ACK,
1278 1.5.12.2 yamt UTOPPY_LONG_TIMEOUT);
1279 1.5.12.2 yamt if (err) {
1280 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1281 1.5.12.2 yamt "utoppy_send_packet(UTOPPY_CMD_ACK) returned %d\n",
1282 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err));
1283 1.5.12.2 yamt utoppy_cancel(sc);
1284 1.5.12.2 yamt return (err);
1285 1.5.12.2 yamt }
1286 1.5.12.2 yamt
1287 1.5.12.2 yamt sc->sc_in_len = 0;
1288 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1289 1.5.12.2 yamt "FILE_HEADER done\n", USBDEVNAME(sc->sc_dev)));
1290 1.5.12.2 yamt break;
1291 1.5.12.2 yamt
1292 1.5.12.2 yamt case UTOPPY_RESP_FILE_DATA:
1293 1.5.12.2 yamt /* Already ACK'd */
1294 1.5.12.2 yamt if (utoppy_get_64(sc, &off)) {
1295 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1296 1.5.12.2 yamt "UTOPPY_RESP_FILE_DATA did not provide offset\n",
1297 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1298 1.5.12.2 yamt utoppy_cancel(sc);
1299 1.5.12.2 yamt return (EBADMSG);
1300 1.5.12.2 yamt }
1301 1.5.12.2 yamt
1302 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1303 1.5.12.2 yamt "UTOPPY_RESP_FILE_DATA: offset %lld, bytes left %ld\n",
1304 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), off, (u_long)sc->sc_in_len));
1305 1.5.12.2 yamt break;
1306 1.5.12.2 yamt
1307 1.5.12.2 yamt case UTOPPY_RESP_FILE_END:
1308 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: "
1309 1.5.12.2 yamt "UTOPPY_RESP_FILE_END: sending ACK\n",
1310 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1311 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1312 1.5.12.2 yamt utoppy_send_packet(sc, UTOPPY_CMD_ACK, UTOPPY_SHORT_TIMEOUT);
1313 1.5.12.2 yamt /*FALLTHROUGH*/
1314 1.5.12.2 yamt
1315 1.5.12.2 yamt case UTOPPY_RESP_SUCCESS:
1316 1.5.12.2 yamt sc->sc_state = UTOPPY_STATE_IDLE;
1317 1.5.12.2 yamt (void) utoppy_turbo_mode(sc, 0);
1318 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: all "
1319 1.5.12.2 yamt "done\n", USBDEVNAME(sc->sc_dev)));
1320 1.5.12.2 yamt break;
1321 1.5.12.2 yamt
1322 1.5.12.2 yamt case UTOPPY_RESP_ERROR:
1323 1.5.12.2 yamt default:
1324 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppy_readfile_next: bad "
1325 1.5.12.2 yamt "response code 0x%0x\n", USBDEVNAME(sc->sc_dev), resp));
1326 1.5.12.2 yamt utoppy_cancel(sc);
1327 1.5.12.2 yamt return (EIO);
1328 1.5.12.2 yamt }
1329 1.5.12.2 yamt
1330 1.5.12.2 yamt return (0);
1331 1.5.12.2 yamt }
1332 1.5.12.2 yamt
1333 1.5.12.2 yamt int
1334 1.5.12.2 yamt utoppyopen(dev_t dev, int flag, int mode, struct lwp *l)
1335 1.5.12.2 yamt {
1336 1.5.12.2 yamt struct utoppy_softc *sc;
1337 1.5.12.2 yamt int error = 0;
1338 1.5.12.2 yamt
1339 1.5.12.2 yamt USB_GET_SC_OPEN(utoppy, UTOPPYUNIT(dev), sc);
1340 1.5.12.2 yamt
1341 1.5.12.2 yamt if (sc == NULL || sc->sc_iface == NULL || sc->sc_dying)
1342 1.5.12.2 yamt return (ENXIO);
1343 1.5.12.2 yamt
1344 1.5.12.2 yamt if (sc->sc_state != UTOPPY_STATE_CLOSED) {
1345 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: already open\n",
1346 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1347 1.5.12.2 yamt return (EBUSY);
1348 1.5.12.2 yamt }
1349 1.5.12.2 yamt
1350 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: opening...\n",
1351 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1352 1.5.12.2 yamt
1353 1.5.12.2 yamt sc->sc_refcnt++;
1354 1.5.12.2 yamt sc->sc_state = UTOPPY_STATE_OPENING;
1355 1.5.12.2 yamt sc->sc_turbo_mode = 0;
1356 1.5.12.2 yamt sc->sc_out_pipe = NULL;
1357 1.5.12.2 yamt sc->sc_in_pipe = NULL;
1358 1.5.12.2 yamt
1359 1.5.12.2 yamt if (usbd_open_pipe(sc->sc_iface, sc->sc_out, 0, &sc->sc_out_pipe)) {
1360 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: usbd_open_pipe(OUT) "
1361 1.5.12.2 yamt "failed\n", USBDEVNAME(sc->sc_dev)));
1362 1.5.12.2 yamt error = EIO;
1363 1.5.12.2 yamt goto done;
1364 1.5.12.2 yamt }
1365 1.5.12.2 yamt
1366 1.5.12.2 yamt if (usbd_open_pipe(sc->sc_iface, sc->sc_in, 0, &sc->sc_in_pipe)) {
1367 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: usbd_open_pipe(IN) "
1368 1.5.12.2 yamt "failed\n", USBDEVNAME(sc->sc_dev)));
1369 1.5.12.2 yamt error = EIO;
1370 1.5.12.2 yamt usbd_close_pipe(sc->sc_out_pipe);
1371 1.5.12.2 yamt sc->sc_out_pipe = NULL;
1372 1.5.12.2 yamt goto done;
1373 1.5.12.2 yamt }
1374 1.5.12.2 yamt
1375 1.5.12.2 yamt sc->sc_out_data = malloc(UTOPPY_BSIZE + 1, M_DEVBUF, M_WAITOK);
1376 1.5.12.2 yamt if (sc->sc_out_data == NULL) {
1377 1.5.12.2 yamt error = ENOMEM;
1378 1.5.12.2 yamt goto error;
1379 1.5.12.2 yamt }
1380 1.5.12.2 yamt
1381 1.5.12.2 yamt sc->sc_in_data = malloc(UTOPPY_BSIZE + 1, M_DEVBUF, M_WAITOK);
1382 1.5.12.2 yamt if (sc->sc_in_data == NULL) {
1383 1.5.12.2 yamt free(sc->sc_out_data, M_DEVBUF);
1384 1.5.12.2 yamt sc->sc_out_data = NULL;
1385 1.5.12.2 yamt error = ENOMEM;
1386 1.5.12.2 yamt goto error;
1387 1.5.12.2 yamt }
1388 1.5.12.2 yamt
1389 1.5.12.2 yamt if ((error = utoppy_cancel(sc)) != 0)
1390 1.5.12.2 yamt goto error;
1391 1.5.12.2 yamt
1392 1.5.12.2 yamt if ((error = utoppy_check_ready(sc)) != 0) {
1393 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: utoppy_check_ready()"
1394 1.5.12.2 yamt " returned %d\n", USBDEVNAME(sc->sc_dev), error));
1395 1.5.12.2 yamt error:
1396 1.5.12.2 yamt usbd_abort_pipe(sc->sc_out_pipe);
1397 1.5.12.2 yamt usbd_close_pipe(sc->sc_out_pipe);
1398 1.5.12.2 yamt sc->sc_out_pipe = NULL;
1399 1.5.12.2 yamt usbd_abort_pipe(sc->sc_in_pipe);
1400 1.5.12.2 yamt usbd_close_pipe(sc->sc_in_pipe);
1401 1.5.12.2 yamt sc->sc_in_pipe = NULL;
1402 1.5.12.2 yamt }
1403 1.5.12.2 yamt
1404 1.5.12.2 yamt done:
1405 1.5.12.2 yamt sc->sc_state = error ? UTOPPY_STATE_CLOSED : UTOPPY_STATE_IDLE;
1406 1.5.12.2 yamt
1407 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_OPEN, ("%s: utoppyopen: done. error %d, new state "
1408 1.5.12.2 yamt "'%s'\n", USBDEVNAME(sc->sc_dev), error,
1409 1.5.12.2 yamt utoppy_state_string(sc->sc_state)));
1410 1.5.12.2 yamt
1411 1.5.12.2 yamt if (--sc->sc_refcnt < 0)
1412 1.5.12.2 yamt usb_detach_wakeup(USBDEV(sc->sc_dev));
1413 1.5.12.2 yamt
1414 1.5.12.2 yamt return (error);
1415 1.5.12.2 yamt }
1416 1.5.12.2 yamt
1417 1.5.12.2 yamt int
1418 1.5.12.2 yamt utoppyclose(dev_t dev, int flag, int mode, struct lwp *l)
1419 1.5.12.2 yamt {
1420 1.5.12.2 yamt struct utoppy_softc *sc;
1421 1.5.12.2 yamt usbd_status err;
1422 1.5.12.2 yamt
1423 1.5.12.2 yamt USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
1424 1.5.12.2 yamt
1425 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: closing...\n",
1426 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1427 1.5.12.2 yamt
1428 1.5.12.2 yamt if (sc->sc_state < UTOPPY_STATE_IDLE) {
1429 1.5.12.2 yamt /* We are being forced to close before the open completed. */
1430 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: not properly open:"
1431 1.5.12.2 yamt " %s\n", USBDEVNAME(sc->sc_dev),
1432 1.5.12.2 yamt utoppy_state_string(sc->sc_state)));
1433 1.5.12.2 yamt return (0);
1434 1.5.12.2 yamt }
1435 1.5.12.2 yamt
1436 1.5.12.2 yamt if (sc->sc_out_data)
1437 1.5.12.2 yamt (void) utoppy_cancel(sc);
1438 1.5.12.2 yamt
1439 1.5.12.2 yamt if (sc->sc_out_pipe != NULL) {
1440 1.5.12.2 yamt if ((err = usbd_abort_pipe(sc->sc_out_pipe)) != 0)
1441 1.5.12.2 yamt printf("usbd_abort_pipe(OUT) returned %d\n", err);
1442 1.5.12.2 yamt if ((err = usbd_close_pipe(sc->sc_out_pipe)) != 0)
1443 1.5.12.2 yamt printf("usbd_close_pipe(OUT) returned %d\n", err);
1444 1.5.12.2 yamt sc->sc_out_pipe = NULL;
1445 1.5.12.2 yamt }
1446 1.5.12.2 yamt
1447 1.5.12.2 yamt if (sc->sc_in_pipe != NULL) {
1448 1.5.12.2 yamt if ((err = usbd_abort_pipe(sc->sc_in_pipe)) != 0)
1449 1.5.12.2 yamt printf("usbd_abort_pipe(IN) returned %d\n", err);
1450 1.5.12.2 yamt if ((err = usbd_close_pipe(sc->sc_in_pipe)) != 0)
1451 1.5.12.2 yamt printf("usbd_close_pipe(IN) returned %d\n", err);
1452 1.5.12.2 yamt sc->sc_in_pipe = NULL;
1453 1.5.12.2 yamt }
1454 1.5.12.2 yamt
1455 1.5.12.2 yamt if (sc->sc_out_data) {
1456 1.5.12.2 yamt free(sc->sc_out_data, M_DEVBUF);
1457 1.5.12.2 yamt sc->sc_out_data = NULL;
1458 1.5.12.2 yamt }
1459 1.5.12.2 yamt
1460 1.5.12.2 yamt if (sc->sc_in_data) {
1461 1.5.12.2 yamt free(sc->sc_in_data, M_DEVBUF);
1462 1.5.12.2 yamt sc->sc_in_data = NULL;
1463 1.5.12.2 yamt }
1464 1.5.12.2 yamt
1465 1.5.12.2 yamt sc->sc_state = UTOPPY_STATE_CLOSED;
1466 1.5.12.2 yamt
1467 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_CLOSE, ("%s: utoppyclose: done.\n",
1468 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1469 1.5.12.2 yamt
1470 1.5.12.2 yamt return (0);
1471 1.5.12.2 yamt }
1472 1.5.12.2 yamt
1473 1.5.12.2 yamt int
1474 1.5.12.2 yamt utoppyread(dev_t dev, struct uio *uio, int flags)
1475 1.5.12.2 yamt {
1476 1.5.12.2 yamt struct utoppy_softc *sc;
1477 1.5.12.2 yamt struct utoppy_dirent ud;
1478 1.5.12.2 yamt size_t len;
1479 1.5.12.2 yamt int err;
1480 1.5.12.2 yamt
1481 1.5.12.2 yamt USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
1482 1.5.12.2 yamt
1483 1.5.12.2 yamt if (sc->sc_dying)
1484 1.5.12.2 yamt return (EIO);
1485 1.5.12.2 yamt
1486 1.5.12.2 yamt sc->sc_refcnt++;
1487 1.5.12.2 yamt
1488 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: reading: state '%s'\n",
1489 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), utoppy_state_string(sc->sc_state)));
1490 1.5.12.2 yamt
1491 1.5.12.2 yamt switch (sc->sc_state) {
1492 1.5.12.2 yamt case UTOPPY_STATE_READDIR:
1493 1.5.12.2 yamt err = 0;
1494 1.5.12.2 yamt while (err == 0 && uio->uio_resid >= sizeof(ud) &&
1495 1.5.12.2 yamt sc->sc_state != UTOPPY_STATE_IDLE) {
1496 1.5.12.2 yamt if (utoppy_readdir_decode(sc, &ud) == 0)
1497 1.5.12.2 yamt err = utoppy_readdir_next(sc);
1498 1.5.12.2 yamt else
1499 1.5.12.2 yamt if ((err = uiomove(&ud, sizeof(ud), uio)) != 0)
1500 1.5.12.2 yamt utoppy_cancel(sc);
1501 1.5.12.2 yamt }
1502 1.5.12.2 yamt break;
1503 1.5.12.2 yamt
1504 1.5.12.2 yamt case UTOPPY_STATE_READFILE:
1505 1.5.12.2 yamt err = 0;
1506 1.5.12.2 yamt while (err == 0 && uio->uio_resid > 0 &&
1507 1.5.12.2 yamt sc->sc_state != UTOPPY_STATE_IDLE) {
1508 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: READFILE: "
1509 1.5.12.2 yamt "resid %ld, bytes_left %ld\n",
1510 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), (u_long)uio->uio_resid,
1511 1.5.12.2 yamt (u_long)sc->sc_in_len));
1512 1.5.12.2 yamt
1513 1.5.12.2 yamt if (sc->sc_in_len == 0 &&
1514 1.5.12.2 yamt (err = utoppy_readfile_next(sc)) != 0) {
1515 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: "
1516 1.5.12.2 yamt "READFILE: utoppy_readfile_next returned "
1517 1.5.12.2 yamt "%d\n", USBDEVNAME(sc->sc_dev), err));
1518 1.5.12.2 yamt break;
1519 1.5.12.2 yamt }
1520 1.5.12.2 yamt
1521 1.5.12.2 yamt len = min(uio->uio_resid, sc->sc_in_len);
1522 1.5.12.2 yamt if (len) {
1523 1.5.12.2 yamt err = uiomove(UTOPPY_IN_DATA(sc), len, uio);
1524 1.5.12.2 yamt if (err == 0) {
1525 1.5.12.2 yamt sc->sc_in_offset += len;
1526 1.5.12.2 yamt sc->sc_in_len -= len;
1527 1.5.12.2 yamt }
1528 1.5.12.2 yamt }
1529 1.5.12.2 yamt }
1530 1.5.12.2 yamt break;
1531 1.5.12.2 yamt
1532 1.5.12.2 yamt case UTOPPY_STATE_IDLE:
1533 1.5.12.2 yamt err = 0;
1534 1.5.12.2 yamt break;
1535 1.5.12.2 yamt
1536 1.5.12.2 yamt case UTOPPY_STATE_WRITEFILE:
1537 1.5.12.2 yamt err = EBUSY;
1538 1.5.12.2 yamt break;
1539 1.5.12.2 yamt
1540 1.5.12.2 yamt default:
1541 1.5.12.2 yamt err = EIO;
1542 1.5.12.2 yamt break;
1543 1.5.12.2 yamt }
1544 1.5.12.2 yamt
1545 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READ, ("%s: utoppyread: done. err %d, state '%s'\n",
1546 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err, utoppy_state_string(sc->sc_state)));
1547 1.5.12.2 yamt
1548 1.5.12.2 yamt if (--sc->sc_refcnt < 0)
1549 1.5.12.2 yamt usb_detach_wakeup(USBDEV(sc->sc_dev));
1550 1.5.12.2 yamt
1551 1.5.12.2 yamt return (err);
1552 1.5.12.2 yamt }
1553 1.5.12.2 yamt
1554 1.5.12.2 yamt int
1555 1.5.12.2 yamt utoppywrite(dev_t dev, struct uio *uio, int flags)
1556 1.5.12.2 yamt {
1557 1.5.12.2 yamt struct utoppy_softc *sc;
1558 1.5.12.2 yamt uint16_t resp;
1559 1.5.12.2 yamt size_t len;
1560 1.5.12.2 yamt int err;
1561 1.5.12.2 yamt
1562 1.5.12.2 yamt USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
1563 1.5.12.2 yamt
1564 1.5.12.2 yamt if (sc->sc_dying)
1565 1.5.12.2 yamt return (EIO);
1566 1.5.12.2 yamt
1567 1.5.12.2 yamt switch(sc->sc_state) {
1568 1.5.12.2 yamt case UTOPPY_STATE_WRITEFILE:
1569 1.5.12.2 yamt break;
1570 1.5.12.2 yamt
1571 1.5.12.2 yamt case UTOPPY_STATE_IDLE:
1572 1.5.12.2 yamt return (0);
1573 1.5.12.2 yamt
1574 1.5.12.2 yamt default:
1575 1.5.12.2 yamt return (EIO);
1576 1.5.12.2 yamt }
1577 1.5.12.2 yamt
1578 1.5.12.2 yamt sc->sc_refcnt++;
1579 1.5.12.2 yamt err = 0;
1580 1.5.12.2 yamt
1581 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: PRE-WRITEFILE: resid %ld, "
1582 1.5.12.2 yamt "wr_size %lld, wr_offset %lld\n", USBDEVNAME(sc->sc_dev),
1583 1.5.12.2 yamt (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset));
1584 1.5.12.2 yamt
1585 1.5.12.2 yamt while (sc->sc_state == UTOPPY_STATE_WRITEFILE &&
1586 1.5.12.2 yamt (len = min(uio->uio_resid, sc->sc_wr_size)) != 0) {
1587 1.5.12.2 yamt
1588 1.5.12.2 yamt len = min(len, UTOPPY_BSIZE - (UTOPPY_HEADER_SIZE +
1589 1.5.12.2 yamt sizeof(uint64_t) + 3));
1590 1.5.12.2 yamt
1591 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove(%ld)\n",
1592 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), (u_long)len));
1593 1.5.12.2 yamt
1594 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1595 1.5.12.2 yamt utoppy_add_64(sc, sc->sc_wr_offset);
1596 1.5.12.2 yamt
1597 1.5.12.2 yamt err = uiomove(utoppy_current_ptr(sc->sc_out_data), len, uio);
1598 1.5.12.2 yamt if (err) {
1599 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: uiomove() "
1600 1.5.12.2 yamt "returned %d\n", USBDEVNAME(sc->sc_dev), err));
1601 1.5.12.2 yamt break;
1602 1.5.12.2 yamt }
1603 1.5.12.2 yamt
1604 1.5.12.2 yamt utoppy_advance_ptr(sc->sc_out_data, len);
1605 1.5.12.2 yamt
1606 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_RESP_FILE_DATA,
1607 1.5.12.2 yamt UTOPPY_LONG_TIMEOUT, &resp);
1608 1.5.12.2 yamt if (err) {
1609 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
1610 1.5.12.2 yamt "utoppy_command(UTOPPY_RESP_FILE_DATA) "
1611 1.5.12.2 yamt "returned %d\n", USBDEVNAME(sc->sc_dev), err));
1612 1.5.12.2 yamt break;
1613 1.5.12.2 yamt }
1614 1.5.12.2 yamt if (resp != UTOPPY_RESP_SUCCESS) {
1615 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
1616 1.5.12.2 yamt "utoppy_command(UTOPPY_RESP_FILE_DATA) returned "
1617 1.5.12.2 yamt "bad response 0x%x\n", USBDEVNAME(sc->sc_dev),
1618 1.5.12.2 yamt resp));
1619 1.5.12.2 yamt utoppy_cancel(sc);
1620 1.5.12.2 yamt err = EIO;
1621 1.5.12.2 yamt break;
1622 1.5.12.2 yamt }
1623 1.5.12.2 yamt
1624 1.5.12.2 yamt sc->sc_wr_offset += len;
1625 1.5.12.2 yamt sc->sc_wr_size -= len;
1626 1.5.12.2 yamt }
1627 1.5.12.2 yamt
1628 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: POST-WRITEFILE: resid %ld,"
1629 1.5.12.2 yamt " wr_size %lld, wr_offset %lld, err %d\n", USBDEVNAME(sc->sc_dev),
1630 1.5.12.2 yamt (u_long)uio->uio_resid, sc->sc_wr_size, sc->sc_wr_offset, err));
1631 1.5.12.2 yamt
1632 1.5.12.2 yamt if (err == 0 && sc->sc_wr_size == 0) {
1633 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: sending "
1634 1.5.12.2 yamt "FILE_END...\n", USBDEVNAME(sc->sc_dev)));
1635 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1636 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_RESP_FILE_END,
1637 1.5.12.2 yamt UTOPPY_LONG_TIMEOUT, &resp);
1638 1.5.12.2 yamt if (err) {
1639 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: "
1640 1.5.12.2 yamt "utoppy_command(UTOPPY_RESP_FILE_END) returned "
1641 1.5.12.2 yamt "%d\n", USBDEVNAME(sc->sc_dev), err));
1642 1.5.12.2 yamt
1643 1.5.12.2 yamt utoppy_cancel(sc);
1644 1.5.12.2 yamt }
1645 1.5.12.2 yamt
1646 1.5.12.2 yamt sc->sc_state = UTOPPY_STATE_IDLE;
1647 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE, ("%s: utoppywrite: state %s\n",
1648 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), utoppy_state_string(sc->sc_state)));
1649 1.5.12.2 yamt }
1650 1.5.12.2 yamt
1651 1.5.12.2 yamt if (--sc->sc_refcnt < 0)
1652 1.5.12.2 yamt usb_detach_wakeup(USBDEV(sc->sc_dev));
1653 1.5.12.2 yamt
1654 1.5.12.2 yamt return (err);
1655 1.5.12.2 yamt }
1656 1.5.12.2 yamt
1657 1.5.12.2 yamt int
1658 1.5.12.2 yamt utoppyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
1659 1.5.12.2 yamt {
1660 1.5.12.2 yamt struct utoppy_softc *sc;
1661 1.5.12.2 yamt struct utoppy_rename *ur;
1662 1.5.12.2 yamt struct utoppy_readfile *urf;
1663 1.5.12.2 yamt struct utoppy_writefile *uw;
1664 1.5.12.2 yamt char uwf[UTOPPY_MAX_FILENAME_LEN + 1], *uwfp;
1665 1.5.12.2 yamt uint16_t resp;
1666 1.5.12.2 yamt int err;
1667 1.5.12.2 yamt
1668 1.5.12.2 yamt USB_GET_SC(utoppy, UTOPPYUNIT(dev), sc);
1669 1.5.12.2 yamt
1670 1.5.12.2 yamt if (sc->sc_dying)
1671 1.5.12.2 yamt return (EIO);
1672 1.5.12.2 yamt
1673 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: cmd 0x%08lx, state '%s'\n",
1674 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), cmd, utoppy_state_string(sc->sc_state)));
1675 1.5.12.2 yamt
1676 1.5.12.2 yamt if (sc->sc_state != UTOPPY_STATE_IDLE && cmd != UTOPPYIOCANCEL) {
1677 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: still busy.\n",
1678 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1679 1.5.12.2 yamt return (EBUSY);
1680 1.5.12.2 yamt }
1681 1.5.12.2 yamt
1682 1.5.12.2 yamt sc->sc_refcnt++;
1683 1.5.12.2 yamt
1684 1.5.12.2 yamt switch (cmd) {
1685 1.5.12.2 yamt case UTOPPYIOTURBO:
1686 1.5.12.2 yamt err = 0;
1687 1.5.12.2 yamt sc->sc_turbo_mode = *((int *)data) ? 1 : 0;
1688 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOTURBO: "
1689 1.5.12.2 yamt "%s\n", USBDEVNAME(sc->sc_dev), sc->sc_turbo_mode ? "On" :
1690 1.5.12.2 yamt "Off"));
1691 1.5.12.2 yamt break;
1692 1.5.12.2 yamt
1693 1.5.12.2 yamt case UTOPPYIOCANCEL:
1694 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOCANCEL\n",
1695 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1696 1.5.12.2 yamt err = utoppy_cancel(sc);
1697 1.5.12.2 yamt break;
1698 1.5.12.2 yamt
1699 1.5.12.2 yamt case UTOPPYIOREBOOT:
1700 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREBOOT\n",
1701 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1702 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1703 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_CMD_RESET, UTOPPY_LONG_TIMEOUT,
1704 1.5.12.2 yamt &resp);
1705 1.5.12.2 yamt if (err)
1706 1.5.12.2 yamt break;
1707 1.5.12.2 yamt
1708 1.5.12.2 yamt if (resp != UTOPPY_RESP_SUCCESS)
1709 1.5.12.2 yamt err = EIO;
1710 1.5.12.2 yamt break;
1711 1.5.12.2 yamt
1712 1.5.12.2 yamt case UTOPPYIOSTATS:
1713 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOSTATS\n",
1714 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1715 1.5.12.2 yamt err = utoppy_stats(sc, (struct utoppy_stats *)data);
1716 1.5.12.2 yamt break;
1717 1.5.12.2 yamt
1718 1.5.12.2 yamt case UTOPPYIORENAME:
1719 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIORENAME\n",
1720 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1721 1.5.12.2 yamt ur = (struct utoppy_rename *)data;
1722 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1723 1.5.12.2 yamt
1724 1.5.12.2 yamt if ((err = utoppy_add_path(sc, ur->ur_old_path, 1)) != 0)
1725 1.5.12.2 yamt break;
1726 1.5.12.2 yamt if ((err = utoppy_add_path(sc, ur->ur_new_path, 1)) != 0)
1727 1.5.12.2 yamt break;
1728 1.5.12.2 yamt
1729 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_CMD_RENAME, UTOPPY_LONG_TIMEOUT,
1730 1.5.12.2 yamt &resp);
1731 1.5.12.2 yamt if (err)
1732 1.5.12.2 yamt break;
1733 1.5.12.2 yamt
1734 1.5.12.2 yamt if (resp != UTOPPY_RESP_SUCCESS)
1735 1.5.12.2 yamt err = EIO;
1736 1.5.12.2 yamt break;
1737 1.5.12.2 yamt
1738 1.5.12.2 yamt case UTOPPYIOMKDIR:
1739 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOMKDIR\n",
1740 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1741 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1742 1.5.12.2 yamt err = utoppy_add_path(sc, *((const char **)data), 1);
1743 1.5.12.2 yamt if (err)
1744 1.5.12.2 yamt break;
1745 1.5.12.2 yamt
1746 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_CMD_MKDIR, UTOPPY_LONG_TIMEOUT,
1747 1.5.12.2 yamt &resp);
1748 1.5.12.2 yamt if (err)
1749 1.5.12.2 yamt break;
1750 1.5.12.2 yamt
1751 1.5.12.2 yamt if (resp != UTOPPY_RESP_SUCCESS)
1752 1.5.12.2 yamt err = EIO;
1753 1.5.12.2 yamt break;
1754 1.5.12.2 yamt
1755 1.5.12.2 yamt case UTOPPYIODELETE:
1756 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIODELETE\n",
1757 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1758 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1759 1.5.12.2 yamt err = utoppy_add_path(sc, *((const char **)data), 0);
1760 1.5.12.2 yamt if (err)
1761 1.5.12.2 yamt break;
1762 1.5.12.2 yamt
1763 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_CMD_DELETE, UTOPPY_LONG_TIMEOUT,
1764 1.5.12.2 yamt &resp);
1765 1.5.12.2 yamt if (err)
1766 1.5.12.2 yamt break;
1767 1.5.12.2 yamt
1768 1.5.12.2 yamt if (resp != UTOPPY_RESP_SUCCESS)
1769 1.5.12.2 yamt err = EIO;
1770 1.5.12.2 yamt break;
1771 1.5.12.2 yamt
1772 1.5.12.2 yamt case UTOPPYIOREADDIR:
1773 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL, ("%s: utoppyioctl: UTOPPYIOREADDIR\n",
1774 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1775 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1776 1.5.12.2 yamt err = utoppy_add_path(sc, *((const char **)data), 0);
1777 1.5.12.2 yamt if (err) {
1778 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
1779 1.5.12.2 yamt "utoppy_add_path() returned %d\n",
1780 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err));
1781 1.5.12.2 yamt break;
1782 1.5.12.2 yamt }
1783 1.5.12.2 yamt
1784 1.5.12.2 yamt err = utoppy_send_packet(sc, UTOPPY_CMD_READDIR,
1785 1.5.12.2 yamt UTOPPY_LONG_TIMEOUT);
1786 1.5.12.2 yamt if (err != 0) {
1787 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
1788 1.5.12.2 yamt "UTOPPY_CMD_READDIR returned %d\n",
1789 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err));
1790 1.5.12.2 yamt break;
1791 1.5.12.2 yamt }
1792 1.5.12.2 yamt
1793 1.5.12.2 yamt err = utoppy_readdir_next(sc);
1794 1.5.12.2 yamt if (err) {
1795 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_READDIR, ("%s: utoppyioctl: "
1796 1.5.12.2 yamt "utoppy_readdir_next() returned %d\n",
1797 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err));
1798 1.5.12.2 yamt }
1799 1.5.12.2 yamt break;
1800 1.5.12.2 yamt
1801 1.5.12.2 yamt case UTOPPYIOREADFILE:
1802 1.5.12.2 yamt urf = (struct utoppy_readfile *)data;
1803 1.5.12.2 yamt
1804 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOREADFILE "
1805 1.5.12.2 yamt "%s, offset %lld\n", USBDEVNAME(sc->sc_dev), urf->ur_path,
1806 1.5.12.2 yamt urf->ur_offset));
1807 1.5.12.2 yamt
1808 1.5.12.2 yamt if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0)
1809 1.5.12.2 yamt break;
1810 1.5.12.2 yamt
1811 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1812 1.5.12.2 yamt utoppy_add_8(sc, UTOPPY_FILE_READ);
1813 1.5.12.2 yamt
1814 1.5.12.2 yamt if ((err = utoppy_add_path(sc, urf->ur_path, 1)) != 0)
1815 1.5.12.2 yamt break;
1816 1.5.12.2 yamt
1817 1.5.12.2 yamt utoppy_add_64(sc, urf->ur_offset);
1818 1.5.12.2 yamt
1819 1.5.12.2 yamt sc->sc_state = UTOPPY_STATE_READFILE;
1820 1.5.12.2 yamt sc->sc_in_offset = 0;
1821 1.5.12.2 yamt
1822 1.5.12.2 yamt err = utoppy_send_packet(sc, UTOPPY_CMD_FILE,
1823 1.5.12.2 yamt UTOPPY_LONG_TIMEOUT);
1824 1.5.12.2 yamt if (err == 0)
1825 1.5.12.2 yamt err = utoppy_readfile_next(sc);
1826 1.5.12.2 yamt break;
1827 1.5.12.2 yamt
1828 1.5.12.2 yamt case UTOPPYIOWRITEFILE:
1829 1.5.12.2 yamt uw = (struct utoppy_writefile *)data;
1830 1.5.12.2 yamt
1831 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: UTOPPYIOWRITEFILE "
1832 1.5.12.2 yamt "%s, size %lld, offset %lld\n", USBDEVNAME(sc->sc_dev),
1833 1.5.12.2 yamt uw->uw_path, uw->uw_size, uw->uw_offset));
1834 1.5.12.2 yamt
1835 1.5.12.2 yamt if ((err = utoppy_turbo_mode(sc, sc->sc_turbo_mode)) != 0)
1836 1.5.12.2 yamt break;
1837 1.5.12.2 yamt
1838 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1839 1.5.12.2 yamt utoppy_add_8(sc, UTOPPY_FILE_WRITE);
1840 1.5.12.2 yamt uwfp = utoppy_current_ptr(sc->sc_out_data);
1841 1.5.12.2 yamt
1842 1.5.12.2 yamt if ((err = utoppy_add_path(sc, uw->uw_path, 1)) != 0) {
1843 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: add_path() "
1844 1.5.12.2 yamt "returned %d\n", USBDEVNAME(sc->sc_dev), err));
1845 1.5.12.2 yamt break;
1846 1.5.12.2 yamt }
1847 1.5.12.2 yamt
1848 1.5.12.2 yamt strncpy(uwf, &uwfp[2], sizeof(uwf));
1849 1.5.12.2 yamt utoppy_add_64(sc, uw->uw_offset);
1850 1.5.12.2 yamt
1851 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_CMD_FILE, UTOPPY_LONG_TIMEOUT,
1852 1.5.12.2 yamt &resp);
1853 1.5.12.2 yamt if (err) {
1854 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
1855 1.5.12.2 yamt "utoppy_command(UTOPPY_CMD_FILE) returned "
1856 1.5.12.2 yamt "%d\n", USBDEVNAME(sc->sc_dev), err));
1857 1.5.12.2 yamt break;
1858 1.5.12.2 yamt }
1859 1.5.12.2 yamt if (resp != UTOPPY_RESP_SUCCESS) {
1860 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
1861 1.5.12.2 yamt "utoppy_command(UTOPPY_CMD_FILE) returned "
1862 1.5.12.2 yamt "bad response 0x%x\n", USBDEVNAME(sc->sc_dev),
1863 1.5.12.2 yamt resp));
1864 1.5.12.2 yamt err = EIO;
1865 1.5.12.2 yamt break;
1866 1.5.12.2 yamt }
1867 1.5.12.2 yamt
1868 1.5.12.2 yamt UTOPPY_OUT_INIT(sc);
1869 1.5.12.2 yamt utoppy_timestamp_encode(sc, uw->uw_mtime);
1870 1.5.12.2 yamt utoppy_add_8(sc, UTOPPY_FTYPE_FILE);
1871 1.5.12.2 yamt utoppy_add_64(sc, uw->uw_size);
1872 1.5.12.2 yamt utoppy_add_string(sc, uwf, sizeof(uwf));
1873 1.5.12.2 yamt utoppy_add_32(sc, 0);
1874 1.5.12.2 yamt
1875 1.5.12.2 yamt err = utoppy_command(sc, UTOPPY_RESP_FILE_HEADER,
1876 1.5.12.2 yamt UTOPPY_LONG_TIMEOUT, &resp);
1877 1.5.12.2 yamt if (err) {
1878 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
1879 1.5.12.2 yamt "utoppy_command(UTOPPY_RESP_FILE_HEADER) "
1880 1.5.12.2 yamt "returned %d\n", USBDEVNAME(sc->sc_dev), err));
1881 1.5.12.2 yamt break;
1882 1.5.12.2 yamt }
1883 1.5.12.2 yamt if (resp != UTOPPY_RESP_SUCCESS) {
1884 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: "
1885 1.5.12.2 yamt "utoppy_command(UTOPPY_RESP_FILE_HEADER) "
1886 1.5.12.2 yamt "returned bad response 0x%x\n",
1887 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), resp));
1888 1.5.12.2 yamt err = EIO;
1889 1.5.12.2 yamt break;
1890 1.5.12.2 yamt }
1891 1.5.12.2 yamt
1892 1.5.12.2 yamt sc->sc_wr_offset = uw->uw_offset;
1893 1.5.12.2 yamt sc->sc_wr_size = uw->uw_size;
1894 1.5.12.2 yamt sc->sc_state = UTOPPY_STATE_WRITEFILE;
1895 1.5.12.2 yamt
1896 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_WRITE,("%s: utoppyioctl: Changing state to "
1897 1.5.12.2 yamt "%s. wr_offset %lld, wr_size %lld\n",
1898 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), utoppy_state_string(sc->sc_state),
1899 1.5.12.2 yamt sc->sc_wr_offset, sc->sc_wr_size));
1900 1.5.12.2 yamt break;
1901 1.5.12.2 yamt
1902 1.5.12.2 yamt default:
1903 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: Invalid cmd\n",
1904 1.5.12.2 yamt USBDEVNAME(sc->sc_dev)));
1905 1.5.12.2 yamt err = ENODEV;
1906 1.5.12.2 yamt break;
1907 1.5.12.2 yamt }
1908 1.5.12.2 yamt
1909 1.5.12.2 yamt DPRINTF(UTOPPY_DBG_IOCTL,("%s: utoppyioctl: done. err %d, state '%s'\n",
1910 1.5.12.2 yamt USBDEVNAME(sc->sc_dev), err, utoppy_state_string(sc->sc_state)));
1911 1.5.12.2 yamt
1912 1.5.12.2 yamt if (err)
1913 1.5.12.2 yamt utoppy_cancel(sc);
1914 1.5.12.2 yamt
1915 1.5.12.2 yamt if (--sc->sc_refcnt < 0)
1916 1.5.12.2 yamt usb_detach_wakeup(USBDEV(sc->sc_dev));
1917 1.5.12.2 yamt
1918 1.5.12.2 yamt return (err);
1919 1.5.12.2 yamt }
1920