diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/usb/media/dabusb.c |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'drivers/usb/media/dabusb.c')
-rw-r--r-- | drivers/usb/media/dabusb.c | 877 |
1 files changed, 877 insertions, 0 deletions
diff --git a/drivers/usb/media/dabusb.c b/drivers/usb/media/dabusb.c new file mode 100644 index 000000000000..8823297d2191 --- /dev/null +++ b/drivers/usb/media/dabusb.c | |||
@@ -0,0 +1,877 @@ | |||
1 | /*****************************************************************************/ | ||
2 | |||
3 | /* | ||
4 | * dabusb.c -- dab usb driver. | ||
5 | * | ||
6 | * Copyright (C) 1999 Deti Fliegl (deti@fliegl.de) | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or | ||
11 | * (at your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | * | ||
22 | * | ||
23 | * | ||
24 | * $Id: dabusb.c,v 1.54 2000/07/24 21:39:39 deti Exp $ | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | /*****************************************************************************/ | ||
29 | |||
30 | #include <linux/module.h> | ||
31 | #include <linux/socket.h> | ||
32 | #include <linux/list.h> | ||
33 | #include <linux/vmalloc.h> | ||
34 | #include <linux/slab.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <asm/uaccess.h> | ||
37 | #include <asm/atomic.h> | ||
38 | #include <linux/delay.h> | ||
39 | #include <linux/usb.h> | ||
40 | #include <linux/smp_lock.h> | ||
41 | |||
42 | #include "dabusb.h" | ||
43 | #include "dabfirmware.h" | ||
44 | |||
45 | /* | ||
46 | * Version Information | ||
47 | */ | ||
48 | #define DRIVER_VERSION "v1.54" | ||
49 | #define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de" | ||
50 | #define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999" | ||
51 | |||
52 | /* --------------------------------------------------------------------- */ | ||
53 | |||
54 | #ifdef CONFIG_USB_DYNAMIC_MINORS | ||
55 | #define NRDABUSB 256 | ||
56 | #else | ||
57 | #define NRDABUSB 4 | ||
58 | #endif | ||
59 | |||
60 | /*-------------------------------------------------------------------*/ | ||
61 | |||
62 | static dabusb_t dabusb[NRDABUSB]; | ||
63 | static int buffers = 256; | ||
64 | static struct usb_driver dabusb_driver; | ||
65 | |||
66 | /*-------------------------------------------------------------------*/ | ||
67 | |||
68 | static int dabusb_add_buf_tail (pdabusb_t s, struct list_head *dst, struct list_head *src) | ||
69 | { | ||
70 | unsigned long flags; | ||
71 | struct list_head *tmp; | ||
72 | int ret = 0; | ||
73 | |||
74 | spin_lock_irqsave (&s->lock, flags); | ||
75 | |||
76 | if (list_empty (src)) { | ||
77 | // no elements in source buffer | ||
78 | ret = -1; | ||
79 | goto err; | ||
80 | } | ||
81 | tmp = src->next; | ||
82 | list_move_tail (tmp, dst); | ||
83 | |||
84 | err: spin_unlock_irqrestore (&s->lock, flags); | ||
85 | return ret; | ||
86 | } | ||
87 | /*-------------------------------------------------------------------*/ | ||
88 | #ifdef DEBUG | ||
89 | static void dump_urb (struct urb *urb) | ||
90 | { | ||
91 | dbg("urb :%p", urb); | ||
92 | dbg("dev :%p", urb->dev); | ||
93 | dbg("pipe :%08X", urb->pipe); | ||
94 | dbg("status :%d", urb->status); | ||
95 | dbg("transfer_flags :%08X", urb->transfer_flags); | ||
96 | dbg("transfer_buffer :%p", urb->transfer_buffer); | ||
97 | dbg("transfer_buffer_length:%d", urb->transfer_buffer_length); | ||
98 | dbg("actual_length :%d", urb->actual_length); | ||
99 | dbg("setup_packet :%p", urb->setup_packet); | ||
100 | dbg("start_frame :%d", urb->start_frame); | ||
101 | dbg("number_of_packets :%d", urb->number_of_packets); | ||
102 | dbg("interval :%d", urb->interval); | ||
103 | dbg("error_count :%d", urb->error_count); | ||
104 | dbg("context :%p", urb->context); | ||
105 | dbg("complete :%p", urb->complete); | ||
106 | } | ||
107 | #endif | ||
108 | /*-------------------------------------------------------------------*/ | ||
109 | static int dabusb_cancel_queue (pdabusb_t s, struct list_head *q) | ||
110 | { | ||
111 | unsigned long flags; | ||
112 | pbuff_t b; | ||
113 | |||
114 | dbg("dabusb_cancel_queue"); | ||
115 | |||
116 | spin_lock_irqsave (&s->lock, flags); | ||
117 | |||
118 | list_for_each_entry(b, q, buff_list) { | ||
119 | #ifdef DEBUG | ||
120 | dump_urb(b->purb); | ||
121 | #endif | ||
122 | usb_unlink_urb (b->purb); | ||
123 | } | ||
124 | spin_unlock_irqrestore (&s->lock, flags); | ||
125 | return 0; | ||
126 | } | ||
127 | /*-------------------------------------------------------------------*/ | ||
128 | static int dabusb_free_queue (struct list_head *q) | ||
129 | { | ||
130 | struct list_head *tmp; | ||
131 | struct list_head *p; | ||
132 | pbuff_t b; | ||
133 | |||
134 | dbg("dabusb_free_queue"); | ||
135 | for (p = q->next; p != q;) { | ||
136 | b = list_entry (p, buff_t, buff_list); | ||
137 | |||
138 | #ifdef DEBUG | ||
139 | dump_urb(b->purb); | ||
140 | #endif | ||
141 | if (b->purb->transfer_buffer) | ||
142 | kfree (b->purb->transfer_buffer); | ||
143 | usb_free_urb(b->purb); | ||
144 | tmp = p->next; | ||
145 | list_del (p); | ||
146 | kfree (b); | ||
147 | p = tmp; | ||
148 | } | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | /*-------------------------------------------------------------------*/ | ||
153 | static int dabusb_free_buffers (pdabusb_t s) | ||
154 | { | ||
155 | unsigned long flags; | ||
156 | dbg("dabusb_free_buffers"); | ||
157 | |||
158 | spin_lock_irqsave(&s->lock, flags); | ||
159 | |||
160 | dabusb_free_queue (&s->free_buff_list); | ||
161 | dabusb_free_queue (&s->rec_buff_list); | ||
162 | |||
163 | spin_unlock_irqrestore(&s->lock, flags); | ||
164 | |||
165 | s->got_mem = 0; | ||
166 | return 0; | ||
167 | } | ||
168 | /*-------------------------------------------------------------------*/ | ||
169 | static void dabusb_iso_complete (struct urb *purb, struct pt_regs *regs) | ||
170 | { | ||
171 | pbuff_t b = purb->context; | ||
172 | pdabusb_t s = b->s; | ||
173 | int i; | ||
174 | int len; | ||
175 | int dst = 0; | ||
176 | void *buf = purb->transfer_buffer; | ||
177 | |||
178 | dbg("dabusb_iso_complete"); | ||
179 | |||
180 | // process if URB was not killed | ||
181 | if (purb->status != -ENOENT) { | ||
182 | unsigned int pipe = usb_rcvisocpipe (purb->dev, _DABUSB_ISOPIPE); | ||
183 | int pipesize = usb_maxpacket (purb->dev, pipe, usb_pipeout (pipe)); | ||
184 | for (i = 0; i < purb->number_of_packets; i++) | ||
185 | if (!purb->iso_frame_desc[i].status) { | ||
186 | len = purb->iso_frame_desc[i].actual_length; | ||
187 | if (len <= pipesize) { | ||
188 | memcpy (buf + dst, buf + purb->iso_frame_desc[i].offset, len); | ||
189 | dst += len; | ||
190 | } | ||
191 | else | ||
192 | err("dabusb_iso_complete: invalid len %d", len); | ||
193 | } | ||
194 | else | ||
195 | warn("dabusb_iso_complete: corrupted packet status: %d", purb->iso_frame_desc[i].status); | ||
196 | if (dst != purb->actual_length) | ||
197 | err("dst!=purb->actual_length:%d!=%d", dst, purb->actual_length); | ||
198 | } | ||
199 | |||
200 | if (atomic_dec_and_test (&s->pending_io) && !s->remove_pending && s->state != _stopped) { | ||
201 | s->overruns++; | ||
202 | err("overrun (%d)", s->overruns); | ||
203 | } | ||
204 | wake_up (&s->wait); | ||
205 | } | ||
206 | /*-------------------------------------------------------------------*/ | ||
207 | static int dabusb_alloc_buffers (pdabusb_t s) | ||
208 | { | ||
209 | int buffers = 0; | ||
210 | pbuff_t b; | ||
211 | unsigned int pipe = usb_rcvisocpipe (s->usbdev, _DABUSB_ISOPIPE); | ||
212 | int pipesize = usb_maxpacket (s->usbdev, pipe, usb_pipeout (pipe)); | ||
213 | int packets = _ISOPIPESIZE / pipesize; | ||
214 | int transfer_buffer_length = packets * pipesize; | ||
215 | int i; | ||
216 | |||
217 | dbg("dabusb_alloc_buffers pipesize:%d packets:%d transfer_buffer_len:%d", | ||
218 | pipesize, packets, transfer_buffer_length); | ||
219 | |||
220 | while (buffers < (s->total_buffer_size << 10)) { | ||
221 | b = (pbuff_t) kmalloc (sizeof (buff_t), GFP_KERNEL); | ||
222 | if (!b) { | ||
223 | err("kmalloc(sizeof(buff_t))==NULL"); | ||
224 | goto err; | ||
225 | } | ||
226 | memset (b, 0, sizeof (buff_t)); | ||
227 | b->s = s; | ||
228 | b->purb = usb_alloc_urb(packets, GFP_KERNEL); | ||
229 | if (!b->purb) { | ||
230 | err("usb_alloc_urb == NULL"); | ||
231 | kfree (b); | ||
232 | goto err; | ||
233 | } | ||
234 | |||
235 | b->purb->transfer_buffer = kmalloc (transfer_buffer_length, GFP_KERNEL); | ||
236 | if (!b->purb->transfer_buffer) { | ||
237 | kfree (b->purb); | ||
238 | kfree (b); | ||
239 | err("kmalloc(%d)==NULL", transfer_buffer_length); | ||
240 | goto err; | ||
241 | } | ||
242 | |||
243 | b->purb->transfer_buffer_length = transfer_buffer_length; | ||
244 | b->purb->number_of_packets = packets; | ||
245 | b->purb->complete = dabusb_iso_complete; | ||
246 | b->purb->context = b; | ||
247 | b->purb->dev = s->usbdev; | ||
248 | b->purb->pipe = pipe; | ||
249 | b->purb->transfer_flags = URB_ISO_ASAP; | ||
250 | |||
251 | for (i = 0; i < packets; i++) { | ||
252 | b->purb->iso_frame_desc[i].offset = i * pipesize; | ||
253 | b->purb->iso_frame_desc[i].length = pipesize; | ||
254 | } | ||
255 | |||
256 | buffers += transfer_buffer_length; | ||
257 | list_add_tail (&b->buff_list, &s->free_buff_list); | ||
258 | } | ||
259 | s->got_mem = buffers; | ||
260 | |||
261 | return 0; | ||
262 | |||
263 | err: | ||
264 | dabusb_free_buffers (s); | ||
265 | return -ENOMEM; | ||
266 | } | ||
267 | /*-------------------------------------------------------------------*/ | ||
268 | static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb) | ||
269 | { | ||
270 | int ret; | ||
271 | unsigned int pipe; | ||
272 | int actual_length; | ||
273 | |||
274 | dbg("dabusb_bulk"); | ||
275 | |||
276 | if (!pb->pipe) | ||
277 | pipe = usb_rcvbulkpipe (s->usbdev, 2); | ||
278 | else | ||
279 | pipe = usb_sndbulkpipe (s->usbdev, 2); | ||
280 | |||
281 | ret=usb_bulk_msg(s->usbdev, pipe, pb->data, pb->size, &actual_length, 100); | ||
282 | if(ret<0) { | ||
283 | err("dabusb: usb_bulk_msg failed(%d)",ret); | ||
284 | |||
285 | if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { | ||
286 | err("set_interface failed"); | ||
287 | return -EINVAL; | ||
288 | } | ||
289 | |||
290 | } | ||
291 | |||
292 | if( ret == -EPIPE ) { | ||
293 | warn("CLEAR_FEATURE request to remove STALL condition."); | ||
294 | if(usb_clear_halt(s->usbdev, usb_pipeendpoint(pipe))) | ||
295 | err("request failed"); | ||
296 | } | ||
297 | |||
298 | pb->size = actual_length; | ||
299 | return ret; | ||
300 | } | ||
301 | /* --------------------------------------------------------------------- */ | ||
302 | static int dabusb_writemem (pdabusb_t s, int pos, unsigned char *data, int len) | ||
303 | { | ||
304 | int ret; | ||
305 | unsigned char *transfer_buffer = kmalloc (len, GFP_KERNEL); | ||
306 | |||
307 | if (!transfer_buffer) { | ||
308 | err("dabusb_writemem: kmalloc(%d) failed.", len); | ||
309 | return -ENOMEM; | ||
310 | } | ||
311 | |||
312 | memcpy (transfer_buffer, data, len); | ||
313 | |||
314 | ret=usb_control_msg(s->usbdev, usb_sndctrlpipe( s->usbdev, 0 ), 0xa0, 0x40, pos, 0, transfer_buffer, len, 300); | ||
315 | |||
316 | kfree (transfer_buffer); | ||
317 | return ret; | ||
318 | } | ||
319 | /* --------------------------------------------------------------------- */ | ||
320 | static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit) | ||
321 | { | ||
322 | dbg("dabusb_8051_reset: %d",reset_bit); | ||
323 | return dabusb_writemem (s, CPUCS_REG, &reset_bit, 1); | ||
324 | } | ||
325 | /* --------------------------------------------------------------------- */ | ||
326 | static int dabusb_loadmem (pdabusb_t s, const char *fname) | ||
327 | { | ||
328 | int ret; | ||
329 | PINTEL_HEX_RECORD ptr = firmware; | ||
330 | |||
331 | dbg("Enter dabusb_loadmem (internal)"); | ||
332 | |||
333 | ret = dabusb_8051_reset (s, 1); | ||
334 | while (ptr->Type == 0) { | ||
335 | |||
336 | dbg("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length); | ||
337 | |||
338 | ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length); | ||
339 | if (ret < 0) { | ||
340 | err("dabusb_writemem failed (%d %04X %p %d)", ret, ptr->Address, ptr->Data, ptr->Length); | ||
341 | break; | ||
342 | } | ||
343 | ptr++; | ||
344 | } | ||
345 | ret = dabusb_8051_reset (s, 0); | ||
346 | |||
347 | dbg("dabusb_loadmem: exit"); | ||
348 | |||
349 | return ret; | ||
350 | } | ||
351 | /* --------------------------------------------------------------------- */ | ||
352 | static int dabusb_fpga_clear (pdabusb_t s, pbulk_transfer_t b) | ||
353 | { | ||
354 | b->size = 4; | ||
355 | b->data[0] = 0x2a; | ||
356 | b->data[1] = 0; | ||
357 | b->data[2] = 0; | ||
358 | b->data[3] = 0; | ||
359 | |||
360 | dbg("dabusb_fpga_clear"); | ||
361 | |||
362 | return dabusb_bulk (s, b); | ||
363 | } | ||
364 | /* --------------------------------------------------------------------- */ | ||
365 | static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b) | ||
366 | { | ||
367 | b->size = 4; | ||
368 | b->data[0] = 0x2c; | ||
369 | b->data[1] = 0; | ||
370 | b->data[2] = 0; | ||
371 | b->data[3] = 0; | ||
372 | |||
373 | dbg("dabusb_fpga_init"); | ||
374 | |||
375 | return dabusb_bulk (s, b); | ||
376 | } | ||
377 | /* --------------------------------------------------------------------- */ | ||
378 | static int dabusb_fpga_download (pdabusb_t s, const char *fname) | ||
379 | { | ||
380 | pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL); | ||
381 | unsigned int blen, n; | ||
382 | int ret; | ||
383 | unsigned char *buf = bitstream; | ||
384 | |||
385 | dbg("Enter dabusb_fpga_download (internal)"); | ||
386 | |||
387 | if (!b) { | ||
388 | err("kmalloc(sizeof(bulk_transfer_t))==NULL"); | ||
389 | return -ENOMEM; | ||
390 | } | ||
391 | |||
392 | b->pipe = 1; | ||
393 | ret = dabusb_fpga_clear (s, b); | ||
394 | mdelay (10); | ||
395 | blen = buf[73] + (buf[72] << 8); | ||
396 | |||
397 | dbg("Bitstream len: %i", blen); | ||
398 | |||
399 | b->data[0] = 0x2b; | ||
400 | b->data[1] = 0; | ||
401 | b->data[2] = 0; | ||
402 | b->data[3] = 60; | ||
403 | |||
404 | for (n = 0; n <= blen + 60; n += 60) { | ||
405 | // some cclks for startup | ||
406 | b->size = 64; | ||
407 | memcpy (b->data + 4, buf + 74 + n, 60); | ||
408 | ret = dabusb_bulk (s, b); | ||
409 | if (ret < 0) { | ||
410 | err("dabusb_bulk failed."); | ||
411 | break; | ||
412 | } | ||
413 | mdelay (1); | ||
414 | } | ||
415 | |||
416 | ret = dabusb_fpga_init (s, b); | ||
417 | kfree (b); | ||
418 | |||
419 | dbg("exit dabusb_fpga_download"); | ||
420 | |||
421 | return ret; | ||
422 | } | ||
423 | |||
424 | static int dabusb_stop (pdabusb_t s) | ||
425 | { | ||
426 | dbg("dabusb_stop"); | ||
427 | |||
428 | s->state = _stopped; | ||
429 | dabusb_cancel_queue (s, &s->rec_buff_list); | ||
430 | |||
431 | dbg("pending_io: %d", s->pending_io.counter); | ||
432 | |||
433 | s->pending_io.counter = 0; | ||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | static int dabusb_startrek (pdabusb_t s) | ||
438 | { | ||
439 | if (!s->got_mem && s->state != _started) { | ||
440 | |||
441 | dbg("dabusb_startrek"); | ||
442 | |||
443 | if (dabusb_alloc_buffers (s) < 0) | ||
444 | return -ENOMEM; | ||
445 | dabusb_stop (s); | ||
446 | s->state = _started; | ||
447 | s->readptr = 0; | ||
448 | } | ||
449 | |||
450 | if (!list_empty (&s->free_buff_list)) { | ||
451 | pbuff_t end; | ||
452 | int ret; | ||
453 | |||
454 | while (!dabusb_add_buf_tail (s, &s->rec_buff_list, &s->free_buff_list)) { | ||
455 | |||
456 | dbg("submitting: end:%p s->rec_buff_list:%p", s->rec_buff_list.prev, &s->rec_buff_list); | ||
457 | |||
458 | end = list_entry (s->rec_buff_list.prev, buff_t, buff_list); | ||
459 | |||
460 | ret = usb_submit_urb (end->purb, GFP_KERNEL); | ||
461 | if (ret) { | ||
462 | err("usb_submit_urb returned:%d", ret); | ||
463 | if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) | ||
464 | err("startrek: dabusb_add_buf_tail failed"); | ||
465 | break; | ||
466 | } | ||
467 | else | ||
468 | atomic_inc (&s->pending_io); | ||
469 | } | ||
470 | dbg("pending_io: %d",s->pending_io.counter); | ||
471 | } | ||
472 | |||
473 | return 0; | ||
474 | } | ||
475 | |||
476 | static ssize_t dabusb_read (struct file *file, char __user *buf, size_t count, loff_t * ppos) | ||
477 | { | ||
478 | pdabusb_t s = (pdabusb_t) file->private_data; | ||
479 | unsigned long flags; | ||
480 | unsigned ret = 0; | ||
481 | int rem; | ||
482 | int cnt; | ||
483 | pbuff_t b; | ||
484 | struct urb *purb = NULL; | ||
485 | |||
486 | dbg("dabusb_read"); | ||
487 | |||
488 | if (*ppos) | ||
489 | return -ESPIPE; | ||
490 | |||
491 | if (s->remove_pending) | ||
492 | return -EIO; | ||
493 | |||
494 | |||
495 | if (!s->usbdev) | ||
496 | return -EIO; | ||
497 | |||
498 | while (count > 0) { | ||
499 | dabusb_startrek (s); | ||
500 | |||
501 | spin_lock_irqsave (&s->lock, flags); | ||
502 | |||
503 | if (list_empty (&s->rec_buff_list)) { | ||
504 | |||
505 | spin_unlock_irqrestore(&s->lock, flags); | ||
506 | |||
507 | err("error: rec_buf_list is empty"); | ||
508 | goto err; | ||
509 | } | ||
510 | |||
511 | b = list_entry (s->rec_buff_list.next, buff_t, buff_list); | ||
512 | purb = b->purb; | ||
513 | |||
514 | spin_unlock_irqrestore(&s->lock, flags); | ||
515 | |||
516 | if (purb->status == -EINPROGRESS) { | ||
517 | if (file->f_flags & O_NONBLOCK) // return nonblocking | ||
518 | { | ||
519 | if (!ret) | ||
520 | ret = -EAGAIN; | ||
521 | goto err; | ||
522 | } | ||
523 | |||
524 | interruptible_sleep_on (&s->wait); | ||
525 | |||
526 | if (signal_pending (current)) { | ||
527 | if (!ret) | ||
528 | ret = -ERESTARTSYS; | ||
529 | goto err; | ||
530 | } | ||
531 | |||
532 | spin_lock_irqsave (&s->lock, flags); | ||
533 | |||
534 | if (list_empty (&s->rec_buff_list)) { | ||
535 | spin_unlock_irqrestore(&s->lock, flags); | ||
536 | err("error: still no buffer available."); | ||
537 | goto err; | ||
538 | } | ||
539 | spin_unlock_irqrestore(&s->lock, flags); | ||
540 | s->readptr = 0; | ||
541 | } | ||
542 | if (s->remove_pending) { | ||
543 | ret = -EIO; | ||
544 | goto err; | ||
545 | } | ||
546 | |||
547 | rem = purb->actual_length - s->readptr; // set remaining bytes to copy | ||
548 | |||
549 | if (count >= rem) | ||
550 | cnt = rem; | ||
551 | else | ||
552 | cnt = count; | ||
553 | |||
554 | dbg("copy_to_user:%p %p %d",buf, purb->transfer_buffer + s->readptr, cnt); | ||
555 | |||
556 | if (copy_to_user (buf, purb->transfer_buffer + s->readptr, cnt)) { | ||
557 | err("read: copy_to_user failed"); | ||
558 | if (!ret) | ||
559 | ret = -EFAULT; | ||
560 | goto err; | ||
561 | } | ||
562 | |||
563 | s->readptr += cnt; | ||
564 | count -= cnt; | ||
565 | buf += cnt; | ||
566 | ret += cnt; | ||
567 | |||
568 | if (s->readptr == purb->actual_length) { | ||
569 | // finished, take next buffer | ||
570 | if (dabusb_add_buf_tail (s, &s->free_buff_list, &s->rec_buff_list)) | ||
571 | err("read: dabusb_add_buf_tail failed"); | ||
572 | s->readptr = 0; | ||
573 | } | ||
574 | } | ||
575 | err: //up(&s->mutex); | ||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | static int dabusb_open (struct inode *inode, struct file *file) | ||
580 | { | ||
581 | int devnum = iminor(inode); | ||
582 | pdabusb_t s; | ||
583 | |||
584 | if (devnum < DABUSB_MINOR || devnum >= (DABUSB_MINOR + NRDABUSB)) | ||
585 | return -EIO; | ||
586 | |||
587 | s = &dabusb[devnum - DABUSB_MINOR]; | ||
588 | |||
589 | dbg("dabusb_open"); | ||
590 | down (&s->mutex); | ||
591 | |||
592 | while (!s->usbdev || s->opened) { | ||
593 | up (&s->mutex); | ||
594 | |||
595 | if (file->f_flags & O_NONBLOCK) { | ||
596 | return -EBUSY; | ||
597 | } | ||
598 | msleep_interruptible(500); | ||
599 | |||
600 | if (signal_pending (current)) { | ||
601 | return -EAGAIN; | ||
602 | } | ||
603 | down (&s->mutex); | ||
604 | } | ||
605 | if (usb_set_interface (s->usbdev, _DABUSB_IF, 1) < 0) { | ||
606 | up(&s->mutex); | ||
607 | err("set_interface failed"); | ||
608 | return -EINVAL; | ||
609 | } | ||
610 | s->opened = 1; | ||
611 | up (&s->mutex); | ||
612 | |||
613 | file->f_pos = 0; | ||
614 | file->private_data = s; | ||
615 | |||
616 | return nonseekable_open(inode, file); | ||
617 | } | ||
618 | |||
619 | static int dabusb_release (struct inode *inode, struct file *file) | ||
620 | { | ||
621 | pdabusb_t s = (pdabusb_t) file->private_data; | ||
622 | |||
623 | dbg("dabusb_release"); | ||
624 | |||
625 | down (&s->mutex); | ||
626 | dabusb_stop (s); | ||
627 | dabusb_free_buffers (s); | ||
628 | up (&s->mutex); | ||
629 | |||
630 | if (!s->remove_pending) { | ||
631 | if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) | ||
632 | err("set_interface failed"); | ||
633 | } | ||
634 | else | ||
635 | wake_up (&s->remove_ok); | ||
636 | |||
637 | s->opened = 0; | ||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | static int dabusb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | ||
642 | { | ||
643 | pdabusb_t s = (pdabusb_t) file->private_data; | ||
644 | pbulk_transfer_t pbulk; | ||
645 | int ret = 0; | ||
646 | int version = DABUSB_VERSION; | ||
647 | |||
648 | dbg("dabusb_ioctl"); | ||
649 | |||
650 | if (s->remove_pending) | ||
651 | return -EIO; | ||
652 | |||
653 | down (&s->mutex); | ||
654 | |||
655 | if (!s->usbdev) { | ||
656 | up (&s->mutex); | ||
657 | return -EIO; | ||
658 | } | ||
659 | |||
660 | switch (cmd) { | ||
661 | |||
662 | case IOCTL_DAB_BULK: | ||
663 | pbulk = (pbulk_transfer_t) kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL); | ||
664 | |||
665 | if (!pbulk) { | ||
666 | ret = -ENOMEM; | ||
667 | break; | ||
668 | } | ||
669 | |||
670 | if (copy_from_user (pbulk, (void __user *) arg, sizeof (bulk_transfer_t))) { | ||
671 | ret = -EFAULT; | ||
672 | kfree (pbulk); | ||
673 | break; | ||
674 | } | ||
675 | |||
676 | ret=dabusb_bulk (s, pbulk); | ||
677 | if(ret==0) | ||
678 | if (copy_to_user((void __user *)arg, pbulk, | ||
679 | sizeof(bulk_transfer_t))) | ||
680 | ret = -EFAULT; | ||
681 | kfree (pbulk); | ||
682 | break; | ||
683 | |||
684 | case IOCTL_DAB_OVERRUNS: | ||
685 | ret = put_user (s->overruns, (unsigned int __user *) arg); | ||
686 | break; | ||
687 | |||
688 | case IOCTL_DAB_VERSION: | ||
689 | ret = put_user (version, (unsigned int __user *) arg); | ||
690 | break; | ||
691 | |||
692 | default: | ||
693 | ret = -ENOIOCTLCMD; | ||
694 | break; | ||
695 | } | ||
696 | up (&s->mutex); | ||
697 | return ret; | ||
698 | } | ||
699 | |||
700 | static struct file_operations dabusb_fops = | ||
701 | { | ||
702 | .owner = THIS_MODULE, | ||
703 | .llseek = no_llseek, | ||
704 | .read = dabusb_read, | ||
705 | .ioctl = dabusb_ioctl, | ||
706 | .open = dabusb_open, | ||
707 | .release = dabusb_release, | ||
708 | }; | ||
709 | |||
710 | static struct usb_class_driver dabusb_class = { | ||
711 | .name = "usb/dabusb%d", | ||
712 | .fops = &dabusb_fops, | ||
713 | .mode = S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, | ||
714 | .minor_base = DABUSB_MINOR, | ||
715 | }; | ||
716 | |||
717 | |||
718 | /* --------------------------------------------------------------------- */ | ||
719 | static int dabusb_probe (struct usb_interface *intf, | ||
720 | const struct usb_device_id *id) | ||
721 | { | ||
722 | struct usb_device *usbdev = interface_to_usbdev(intf); | ||
723 | int retval; | ||
724 | pdabusb_t s; | ||
725 | |||
726 | dbg("dabusb: probe: vendor id 0x%x, device id 0x%x ifnum:%d", | ||
727 | le16_to_cpu(usbdev->descriptor.idVendor), | ||
728 | le16_to_cpu(usbdev->descriptor.idProduct), | ||
729 | intf->altsetting->desc.bInterfaceNumber); | ||
730 | |||
731 | /* We don't handle multiple configurations */ | ||
732 | if (usbdev->descriptor.bNumConfigurations != 1) | ||
733 | return -ENODEV; | ||
734 | |||
735 | if (intf->altsetting->desc.bInterfaceNumber != _DABUSB_IF && | ||
736 | le16_to_cpu(usbdev->descriptor.idProduct) == 0x9999) | ||
737 | return -ENODEV; | ||
738 | |||
739 | |||
740 | |||
741 | s = &dabusb[intf->minor]; | ||
742 | |||
743 | down (&s->mutex); | ||
744 | s->remove_pending = 0; | ||
745 | s->usbdev = usbdev; | ||
746 | s->devnum = intf->minor; | ||
747 | |||
748 | if (usb_reset_configuration (usbdev) < 0) { | ||
749 | err("reset_configuration failed"); | ||
750 | goto reject; | ||
751 | } | ||
752 | if (le16_to_cpu(usbdev->descriptor.idProduct) == 0x2131) { | ||
753 | dabusb_loadmem (s, NULL); | ||
754 | goto reject; | ||
755 | } | ||
756 | else { | ||
757 | dabusb_fpga_download (s, NULL); | ||
758 | |||
759 | if (usb_set_interface (s->usbdev, _DABUSB_IF, 0) < 0) { | ||
760 | err("set_interface failed"); | ||
761 | goto reject; | ||
762 | } | ||
763 | } | ||
764 | dbg("bound to interface: %d", intf->altsetting->desc.bInterfaceNumber); | ||
765 | usb_set_intfdata (intf, s); | ||
766 | up (&s->mutex); | ||
767 | |||
768 | retval = usb_register_dev(intf, &dabusb_class); | ||
769 | if (retval) { | ||
770 | usb_set_intfdata (intf, NULL); | ||
771 | return -ENOMEM; | ||
772 | } | ||
773 | |||
774 | return 0; | ||
775 | |||
776 | reject: | ||
777 | up (&s->mutex); | ||
778 | s->usbdev = NULL; | ||
779 | return -ENODEV; | ||
780 | } | ||
781 | |||
782 | static void dabusb_disconnect (struct usb_interface *intf) | ||
783 | { | ||
784 | wait_queue_t __wait; | ||
785 | pdabusb_t s = usb_get_intfdata (intf); | ||
786 | |||
787 | dbg("dabusb_disconnect"); | ||
788 | |||
789 | init_waitqueue_entry(&__wait, current); | ||
790 | |||
791 | usb_set_intfdata (intf, NULL); | ||
792 | if (s) { | ||
793 | usb_deregister_dev (intf, &dabusb_class); | ||
794 | s->remove_pending = 1; | ||
795 | wake_up (&s->wait); | ||
796 | add_wait_queue(&s->remove_ok, &__wait); | ||
797 | set_current_state(TASK_UNINTERRUPTIBLE); | ||
798 | if (s->state == _started) | ||
799 | schedule(); | ||
800 | current->state = TASK_RUNNING; | ||
801 | remove_wait_queue(&s->remove_ok, &__wait); | ||
802 | |||
803 | s->usbdev = NULL; | ||
804 | s->overruns = 0; | ||
805 | } | ||
806 | } | ||
807 | |||
808 | static struct usb_device_id dabusb_ids [] = { | ||
809 | // { USB_DEVICE(0x0547, 0x2131) }, /* An2131 chip, no boot ROM */ | ||
810 | { USB_DEVICE(0x0547, 0x9999) }, | ||
811 | { } /* Terminating entry */ | ||
812 | }; | ||
813 | |||
814 | MODULE_DEVICE_TABLE (usb, dabusb_ids); | ||
815 | |||
816 | static struct usb_driver dabusb_driver = { | ||
817 | .owner = THIS_MODULE, | ||
818 | .name = "dabusb", | ||
819 | .probe = dabusb_probe, | ||
820 | .disconnect = dabusb_disconnect, | ||
821 | .id_table = dabusb_ids, | ||
822 | }; | ||
823 | |||
824 | /* --------------------------------------------------------------------- */ | ||
825 | |||
826 | static int __init dabusb_init (void) | ||
827 | { | ||
828 | int retval; | ||
829 | unsigned u; | ||
830 | |||
831 | /* initialize struct */ | ||
832 | for (u = 0; u < NRDABUSB; u++) { | ||
833 | pdabusb_t s = &dabusb[u]; | ||
834 | memset (s, 0, sizeof (dabusb_t)); | ||
835 | init_MUTEX (&s->mutex); | ||
836 | s->usbdev = NULL; | ||
837 | s->total_buffer_size = buffers; | ||
838 | init_waitqueue_head (&s->wait); | ||
839 | init_waitqueue_head (&s->remove_ok); | ||
840 | spin_lock_init (&s->lock); | ||
841 | INIT_LIST_HEAD (&s->free_buff_list); | ||
842 | INIT_LIST_HEAD (&s->rec_buff_list); | ||
843 | } | ||
844 | |||
845 | /* register misc device */ | ||
846 | retval = usb_register(&dabusb_driver); | ||
847 | if (retval) | ||
848 | goto out; | ||
849 | |||
850 | dbg("dabusb_init: driver registered"); | ||
851 | |||
852 | info(DRIVER_VERSION ":" DRIVER_DESC); | ||
853 | |||
854 | out: | ||
855 | return retval; | ||
856 | } | ||
857 | |||
858 | static void __exit dabusb_cleanup (void) | ||
859 | { | ||
860 | dbg("dabusb_cleanup"); | ||
861 | |||
862 | usb_deregister (&dabusb_driver); | ||
863 | } | ||
864 | |||
865 | /* --------------------------------------------------------------------- */ | ||
866 | |||
867 | MODULE_AUTHOR( DRIVER_AUTHOR ); | ||
868 | MODULE_DESCRIPTION( DRIVER_DESC ); | ||
869 | MODULE_LICENSE("GPL"); | ||
870 | |||
871 | module_param(buffers, int, 0); | ||
872 | MODULE_PARM_DESC (buffers, "Number of buffers (default=256)"); | ||
873 | |||
874 | module_init (dabusb_init); | ||
875 | module_exit (dabusb_cleanup); | ||
876 | |||
877 | /* --------------------------------------------------------------------- */ | ||