This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / media / dvb / b2c2 / b2c2-usb-core.c
1 /*
2  * Copyright (C) 2004 Patrick Boettcher <patrick.boettcher@desy.de>,
3  *                    Luca Bertagnolio <>,
4  *
5  * based on information provided by John Jurrius from BBTI, Inc.
6  *
7  *      This program is free software; you can redistribute it and/or
8  *      modify it under the terms of the GNU General Public License as
9  *      published by the Free Software Foundation, version 2.
10  *
11  */
12
13 #include <linux/config.h>
14 #include <linux/kernel.h>
15 #include <linux/usb.h>
16 #include <linux/moduleparam.h>
17 #include <linux/pci.h>
18 #include <linux/version.h>
19
20 #include "dmxdev.h"
21 #include "dvb_demux.h"
22 #include "dvb_filter.h"
23 #include "dvb_net.h"
24 #include "dvb_frontend.h"
25
26 /* debug */
27 #define dprintk(level,args...) \
28             do { if ((debug & level)) { printk(args); } } while (0)
29 #define debug_dump(b,l) if (debug) {\
30         int i; deb_xfer("%s: %d > ",__FUNCTION__,l); \
31         for (i = 0; i < l; i++) deb_xfer("%02x ", b[i]); \
32         deb_xfer("\n");\
33 }
34
35 static int debug;
36 module_param(debug, int, 0x644);
37 MODULE_PARM_DESC(debug, "set debugging level (1=info,ts=2,ctrl=4 (or-able)).");
38
39 #define deb_info(args...) dprintk(0x01,args)
40 #define deb_ts(args...)   dprintk(0x02,args)
41 #define deb_ctrl(args...) dprintk(0x04,args)
42
43 /* Version information */
44 #define DRIVER_VERSION "0.0"
45 #define DRIVER_DESC "Driver for B2C2/Technisat Air/Cable/Sky-2-PC USB devices"
46 #define DRIVER_AUTHOR "Patrick Boettcher, patrick.boettcher@desy.de"
47
48 /* transfer parameters */
49 #define B2C2_USB_FRAMES_PER_ISO         4
50 #define B2C2_USB_NUM_ISO_URB            4    /* TODO check out a good value */
51
52 #define B2C2_USB_CTRL_PIPE_IN           usb_rcvctrlpipe(b2c2->udev,0)
53 #define B2C2_USB_CTRL_PIPE_OUT          usb_sndctrlpipe(b2c2->udev,0)
54 #define B2C2_USB_DATA_PIPE                      usb_rcvisocpipe(b2c2->udev,0x81)
55
56 struct usb_b2c2_usb {
57         struct usb_device *udev;
58         struct usb_interface *uintf;
59
60         u8 *iso_buffer;
61         int buffer_size;
62         dma_addr_t iso_dma_handle;
63         struct urb *iso_urb[B2C2_USB_NUM_ISO_URB];
64 };
65
66
67 /*
68  * USB
69  * 10 90 34 12 78 56 04 00
70  * usb_control_msg(udev, usb_sndctrlpipe(udev,0),
71  * 0x90,
72  * 0x10,
73  * 0x1234,
74  * 0x5678,
75  * buf,
76  * 4,
77  * 5*HZ);
78  *
79  * extern int usb_control_msg(struct usb_device *dev, unsigned int pipe,
80  * __u8 request,
81  * __u8 requesttype,
82  * __u16 value,
83  * __u16 index,
84  * void *data,
85  * __u16 size,
86  * int timeout);
87  *
88  */
89
90 /* request types */
91 typedef enum {
92         RTYPE_READ_DW         = (1 << 6),
93         RTYPE_WRITE_DW_1      = (3 << 6),
94         RTYPE_READ_V8_MEMORY  = (6 << 6),
95         RTYPE_WRITE_V8_MEMORY = (7 << 6),
96         RTYPE_WRITE_V8_FLASH  = (8 << 6),
97         RTYPE_GENERIC         = (9 << 6),
98 } b2c2_usb_request_type_t;
99
100 /* request */
101 typedef enum {
102         B2C2_USB_WRITE_V8_MEM = 0x04,
103         B2C2_USB_READ_V8_MEM  = 0x05,
104         B2C2_USB_READ_REG     = 0x08,
105         B2C2_USB_WRITE_REG    = 0x0A,
106 /*      B2C2_USB_WRITEREGLO   = 0x0A, */
107         B2C2_USB_WRITEREGHI   = 0x0B,
108         B2C2_USB_FLASH_BLOCK  = 0x10,
109         B2C2_USB_I2C_REQUEST  = 0x11,
110         B2C2_USB_UTILITY      = 0x12,
111 } b2c2_usb_request_t;
112
113 /* function definition for I2C_REQUEST */
114 typedef enum {
115         USB_FUNC_I2C_WRITE       = 0x01,
116         USB_FUNC_I2C_MULTIWRITE  = 0x02,
117         USB_FUNC_I2C_READ        = 0x03,
118         USB_FUNC_I2C_REPEATWRITE = 0x04,
119         USB_FUNC_GET_DESCRIPTOR  = 0x05,
120         USB_FUNC_I2C_REPEATREAD  = 0x06,
121 /* DKT 020208 - add this to support special case of DiSEqC */
122         USB_FUNC_I2C_CHECKWRITE  = 0x07,
123         USB_FUNC_I2C_CHECKRESULT = 0x08,
124 } b2c2_usb_i2c_function_t;
125
126 /*
127  * function definition for UTILITY request 0x12
128  * DKT 020304 - new utility function
129  */
130 typedef enum {
131         UTILITY_SET_FILTER          = 0x01,
132         UTILITY_DATA_ENABLE         = 0x02,
133         UTILITY_FLEX_MULTIWRITE     = 0x03,
134         UTILITY_SET_BUFFER_SIZE     = 0x04,
135         UTILITY_FLEX_OPERATOR       = 0x05,
136         UTILITY_FLEX_RESET300_START = 0x06,
137         UTILITY_FLEX_RESET300_STOP  = 0x07,
138         UTILITY_FLEX_RESET300       = 0x08,
139         UTILITY_SET_ISO_SIZE        = 0x09,
140         UTILITY_DATA_RESET          = 0x0A,
141         UTILITY_GET_DATA_STATUS     = 0x10,
142         UTILITY_GET_V8_REG          = 0x11,
143 /* DKT 020326 - add function for v1.14 */
144         UTILITY_SRAM_WRITE          = 0x12,
145         UTILITY_SRAM_READ           = 0x13,
146         UTILITY_SRAM_TESTFILL       = 0x14,
147         UTILITY_SRAM_TESTSET        = 0x15,
148         UTILITY_SRAM_TESTVERIFY     = 0x16,
149 } b2c2_usb_utility_function_t;
150
151 #define B2C2_WAIT_FOR_OPERATION_RW  1  // 1 s
152 #define B2C2_WAIT_FOR_OPERATION_RDW 3  // 3 s
153 #define B2C2_WAIT_FOR_OPERATION_WDW 1  // 1 s
154
155 #define B2C2_WAIT_FOR_OPERATION_V8READ   3  // 3 s
156 #define B2C2_WAIT_FOR_OPERATION_V8WRITE  3  // 3 s
157 #define B2C2_WAIT_FOR_OPERATION_V8FLASH  3  // 3 s
158
159 /* JLP 111700: we will include the 1 bit gap between the upper and lower 3 bits
160  * in the IBI address, to make the V8 code simpler.
161  * PCI ADDRESS FORMAT: 0x71C -> 0000 0111 0001 1100 (these are the six bits used)
162  *                  in general: 0000 0HHH 000L LL00
163  * IBI ADDRESS FORMAT:                    RHHH BLLL
164  *
165  * where R is the read(1)/write(0) bit, B is the busy bit
166  * and HHH and LLL are the two sets of three bits from the PCI address.
167  */
168 #define B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(usPCI) (u8) (((usPCI >> 2) & 0x07) + ((usPCI >> 4) & 0x70))
169 #define B2C2_FLEX_INTERNALADDR_TO_PCIOFFSET(ucAddr) (u16) (((ucAddr & 0x07) << 2) + ((ucAddr & 0x70) << 4))
170
171 /*
172  * DKT 020228 - forget about this VENDOR_BUFFER_SIZE, read and write register
173  * deal with DWORD or 4 bytes, that should be should from now on
174  */
175 static u32 b2c2_usb_read_dw(struct usb_b2c2_usb *b2c2, u16 wRegOffsPCI)
176 {
177         u32 val;
178         u16 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) | 0x0080;
179         int len = usb_control_msg(b2c2->udev,
180                         B2C2_USB_CTRL_PIPE_IN,
181                         B2C2_USB_READ_REG,
182                         RTYPE_READ_DW,
183                         wAddress,
184                         0,
185                         &val,
186                         sizeof(u32),
187                         B2C2_WAIT_FOR_OPERATION_RDW * HZ);
188
189         if (len != sizeof(u32)) {
190                 err("error while reading dword from %d (%d).",wAddress,wRegOffsPCI);
191                 return -EIO;
192         } else
193                 return val;
194 }
195
196 /*
197  * DKT 020228 - from now on, we don't support anything older than firm 1.00
198  * I eliminated the write register as a 2 trip of writing hi word and lo word
199  * and force this to write only 4 bytes at a time.
200  * NOTE: this should work with all the firmware from 1.00 and newer
201  */
202 static int b2c2_usb_write_dw(struct usb_b2c2_usb *b2c2, u16 wRegOffsPCI, u32 val)
203 {
204         u16 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI);
205         int len = usb_control_msg(b2c2->udev,
206                         B2C2_USB_CTRL_PIPE_OUT,
207                         B2C2_USB_WRITE_REG,
208                         RTYPE_WRITE_DW_1,
209                         wAddress,
210                         0,
211                         &val,
212                         sizeof(u32),
213                         B2C2_WAIT_FOR_OPERATION_RDW * HZ);
214
215         if (len != sizeof(u32)) {
216                 err("error while reading dword from %d (%d).",wAddress,wRegOffsPCI);
217                 return -EIO;
218         } else
219                 return 0;
220 }
221
222 /*
223  * DKT 010817 - add support for V8 memory read/write and flash update
224  */
225 static int b2c2_usb_v8_memory_req(struct usb_b2c2_usb *b2c2,
226                 b2c2_usb_request_t req, u8 page, u16 wAddress,
227                 u16 buflen, u8 *pbBuffer)
228 {
229         u8 dwRequestType;
230         u16 wIndex;
231         int nWaitTime,pipe,len;
232
233         wIndex = page << 8;
234
235         switch (req) {
236                 case B2C2_USB_READ_V8_MEM:
237                         nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ;
238                         dwRequestType = (u8) RTYPE_READ_V8_MEMORY;
239                         pipe = B2C2_USB_CTRL_PIPE_IN;
240                 break;
241                 case B2C2_USB_WRITE_V8_MEM:
242                         wIndex |= pbBuffer[0];
243                         nWaitTime = B2C2_WAIT_FOR_OPERATION_V8WRITE;
244                         dwRequestType = (u8) RTYPE_WRITE_V8_MEMORY;
245                         pipe = B2C2_USB_CTRL_PIPE_OUT;
246                 break;
247                 case B2C2_USB_FLASH_BLOCK:
248                         nWaitTime = B2C2_WAIT_FOR_OPERATION_V8FLASH;
249                         dwRequestType = (u8) RTYPE_WRITE_V8_FLASH;
250                         pipe = B2C2_USB_CTRL_PIPE_OUT;
251                 break;
252                 default:
253                         deb_info("unsupported request for v8_mem_req %x.\n",req);
254                 return -EINVAL;
255         }
256         len = usb_control_msg(b2c2->udev,pipe,
257                         req,
258                         dwRequestType,
259                         wAddress,
260                         wIndex,
261                         pbBuffer,
262                         buflen,
263                         nWaitTime * HZ);
264         return len == buflen ? 0 : -EIO;
265 }
266
267 static int b2c2_usb_i2c_req(struct usb_b2c2_usb *b2c2,
268                 b2c2_usb_request_t req, b2c2_usb_i2c_function_t func,
269                 u8 port, u8 chipaddr, u8 addr, u8 buflen, u8 *buf)
270 {
271         u16 wValue, wIndex;
272         int nWaitTime,pipe,len;
273         u8 dwRequestType;
274
275         switch (func) {
276                 case USB_FUNC_I2C_WRITE:
277                 case USB_FUNC_I2C_MULTIWRITE:
278                 case USB_FUNC_I2C_REPEATWRITE:
279                 /* DKT 020208 - add this to support special case of DiSEqC */
280                 case USB_FUNC_I2C_CHECKWRITE:
281                         pipe = B2C2_USB_CTRL_PIPE_OUT;
282                         nWaitTime = 2;
283                         dwRequestType = (u8) RTYPE_GENERIC;
284                 break;
285                 case USB_FUNC_I2C_READ:
286                 case USB_FUNC_I2C_REPEATREAD:
287                         pipe = B2C2_USB_CTRL_PIPE_IN;
288                         nWaitTime = 2;
289                         dwRequestType = (u8) RTYPE_GENERIC;
290                 break;
291                 default:
292                         deb_info("unsupported function for i2c_req %x\n",func);
293                         return -EINVAL;
294         }
295         wValue = (func << 8 ) | port;
296         wIndex = (chipaddr << 8 ) | addr;
297
298         len = usb_control_msg(b2c2->udev,pipe,
299                         req,
300                         dwRequestType,
301                         addr,
302                         wIndex,
303                         buf,
304                         buflen,
305                         nWaitTime * HZ);
306         return len == buflen ? 0 : -EIO;
307 }
308
309 int static b2c2_usb_utility_req(struct usb_b2c2_usb *b2c2, int set,
310                 b2c2_usb_utility_function_t func, u8 extra, u16 wIndex,
311                 u16 buflen, u8 *pvBuffer)
312 {
313         u16 wValue;
314         int nWaitTime = 2,
315                 pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN,
316                 len;
317
318         wValue = (func << 8) | extra;
319
320         len = usb_control_msg(b2c2->udev,pipe,
321                         B2C2_USB_UTILITY,
322                         (u8) RTYPE_GENERIC,
323                         wValue,
324                         wIndex,
325                         pvBuffer,
326                         buflen,
327                         nWaitTime * HZ);
328         return len == buflen ? 0 : -EIO;
329 }
330
331
332
333 static void b2c2_dumpfourreg(struct usb_b2c2_usb *b2c2, u16 offs)
334 {
335         u32 r0,r1,r2,r3;
336         r0 = r1 = r2 = r3 = 0;
337         r0 = b2c2_usb_read_dw(b2c2,offs);
338         r1 = b2c2_usb_read_dw(b2c2,offs + 0x04);
339         r2 = b2c2_usb_read_dw(b2c2,offs + 0x08);
340         r3 = b2c2_usb_read_dw(b2c2,offs + 0x0c);
341         deb_ctrl("dump: offset: %03x, %08x, %08x, %08x, %08x\n",offs,r0,r1,r2,r3);
342 }
343
344 static void b2c2_urb_complete(struct urb *urb, struct pt_regs *ptregs)
345 {
346         struct usb_b2c2_usb *b2c2 = urb->context;
347         deb_ts("urb completed, bufsize: %d\n",urb->transfer_buffer_length);
348
349 //      urb_submit_urb(urb,GFP_ATOMIC); enable for real action
350 }
351
352 static void b2c2_exit_usb(struct usb_b2c2_usb *b2c2)
353 {
354         int i;
355         for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
356                 if (b2c2->iso_urb[i] != NULL) { /* not sure about unlink_urb and iso-urbs TODO */
357                         deb_info("unlinking/killing urb no. %d\n",i);
358 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,7)
359                         usb_unlink_urb(b2c2->iso_urb[i]);
360 #else
361                         usb_kill_urb(b2c2->iso_urb[i]);
362 #endif
363                         usb_free_urb(b2c2->iso_urb[i]);
364                 }
365
366         if (b2c2->iso_buffer != NULL)
367                 pci_free_consistent(NULL,b2c2->buffer_size, b2c2->iso_buffer, b2c2->iso_dma_handle);
368
369 }
370
371 static int b2c2_init_usb(struct usb_b2c2_usb *b2c2)
372 {
373         u16 frame_size = b2c2->uintf->cur_altsetting->endpoint[0].desc.wMaxPacketSize;
374         int bufsize = B2C2_USB_NUM_ISO_URB * B2C2_USB_FRAMES_PER_ISO * frame_size,i,j,ret;
375         int buffer_offset = 0;
376
377         deb_info("creating %d iso-urbs with %d frames each of %d bytes size = %d.\n",
378                         B2C2_USB_NUM_ISO_URB, B2C2_USB_FRAMES_PER_ISO, frame_size,bufsize);
379
380         b2c2->iso_buffer = pci_alloc_consistent(NULL,bufsize,&b2c2->iso_dma_handle);
381         if (b2c2->iso_buffer == NULL)
382                 return -ENOMEM;
383         memset(b2c2->iso_buffer, 0, bufsize);
384         b2c2->buffer_size = bufsize;
385
386         /* creating iso urbs */
387         for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++)
388                 if (!(b2c2->iso_urb[i] = usb_alloc_urb(B2C2_USB_FRAMES_PER_ISO,GFP_ATOMIC))) {
389                         ret = -ENOMEM;
390                         goto urb_error;
391                 }
392         /* initialising and submitting iso urbs */
393         for (i = 0; i < B2C2_USB_NUM_ISO_URB; i++) {
394                 deb_info("initializing and submitting urb no. %d (buf_offset: %d).\n",i,buffer_offset);
395                 int frame_offset = 0;
396                 struct urb *urb = b2c2->iso_urb[i];
397
398                 urb->dev = b2c2->udev;
399                 urb->context = b2c2;
400                 urb->complete = b2c2_urb_complete;
401                 urb->pipe = B2C2_USB_DATA_PIPE;
402                 urb->transfer_flags = URB_ISO_ASAP;
403                 urb->interval = 1;
404                 urb->number_of_packets = B2C2_USB_FRAMES_PER_ISO;
405                 urb->transfer_buffer_length = frame_size * B2C2_USB_FRAMES_PER_ISO;
406                 urb->transfer_buffer = b2c2->iso_buffer + buffer_offset;
407
408                 buffer_offset += frame_size * B2C2_USB_FRAMES_PER_ISO;
409                 for (j = 0; j < B2C2_USB_FRAMES_PER_ISO; j++) {
410                         deb_info("urb no: %d, frame: %d, frame_offset: %d\n",i,j,frame_offset);
411                         urb->iso_frame_desc[j].offset = frame_offset;
412                         urb->iso_frame_desc[j].length = frame_size;
413                         frame_offset += frame_size;
414                 }
415
416                 if ((ret = usb_submit_urb(b2c2->iso_urb[i],GFP_ATOMIC))) {
417                         err("submitting urb %d failed with %d.",i,ret);
418                         goto urb_error;
419                 }
420                 deb_info("submitted urb no. %d.\n",i);
421         }
422
423         ret = 0;
424         goto success;
425 urb_error:
426         b2c2_exit_usb(b2c2);
427 success:
428         return ret;
429 }
430
431 static int b2c2_usb_probe(struct usb_interface *intf,
432                 const struct usb_device_id *id)
433 {
434         struct usb_device *udev = interface_to_usbdev(intf);
435         struct usb_b2c2_usb *b2c2 = NULL;
436         int ret;
437
438         b2c2 = kmalloc(sizeof(struct usb_b2c2_usb),GFP_KERNEL);
439         if (b2c2 == NULL) {
440                 err("no memory");
441                 return -ENOMEM;
442         }
443         b2c2->udev = udev;
444         b2c2->uintf = intf;
445
446         /* use the alternate setting with the larges buffer */
447         usb_set_interface(udev,0,1);
448
449         if ((ret = b2c2_init_usb(b2c2)))
450                 goto usb_init_error;
451
452         usb_set_intfdata(intf,b2c2);
453
454         switch (udev->speed) {
455                 case USB_SPEED_LOW:
456                         err("cannot handle USB speed because it is to sLOW.");
457                         break;
458                 case USB_SPEED_FULL:
459                         info("running at FULL speed.");
460                         break;
461                 case USB_SPEED_HIGH:
462                         info("running at HIGH speed.");
463                         break;
464                 case USB_SPEED_UNKNOWN: /* fall through */
465                 default:
466                         err("cannot handle USB speed because it is unkown.");
467                 break;
468         }
469
470         b2c2_dumpfourreg(b2c2,0x200);
471         b2c2_dumpfourreg(b2c2,0x300);
472         b2c2_dumpfourreg(b2c2,0x400);
473         b2c2_dumpfourreg(b2c2,0x700);
474
475
476         if (ret == 0)
477                 info("%s successfully initialized and connected.",DRIVER_DESC);
478         else
479                 info("%s error while loading driver (%d)",DRIVER_DESC,ret);
480
481         ret = 0;
482         goto success;
483
484 usb_init_error:
485         kfree(b2c2);
486 success:
487         return ret;
488 }
489
490 static void b2c2_usb_disconnect(struct usb_interface *intf)
491 {
492         struct usb_b2c2_usb *b2c2 = usb_get_intfdata(intf);
493         usb_set_intfdata(intf,NULL);
494         if (b2c2 != NULL) {
495                 b2c2_exit_usb(b2c2);
496                 kfree(b2c2);
497         }
498         info("%s successfully deinitialized and disconnected.",DRIVER_DESC);
499
500 }
501
502 static struct usb_device_id b2c2_usb_table [] = {
503             { USB_DEVICE(0x0af7, 0x0101) }
504 };
505
506 /* usb specific object needed to register this driver with the usb subsystem */
507 static struct usb_driver b2c2_usb_driver = {
508         .owner          = THIS_MODULE,
509         .name           = "dvb_b2c2_usb",
510         .probe          = b2c2_usb_probe,
511         .disconnect = b2c2_usb_disconnect,
512         .id_table       = b2c2_usb_table,
513 };
514
515 /* module stuff */
516 static int __init b2c2_usb_init(void)
517 {
518         int result;
519         if ((result = usb_register(&b2c2_usb_driver))) {
520                 err("usb_register failed. Error number %d",result);
521                 return result;
522         }
523
524         return 0;
525 }
526
527 static void __exit b2c2_usb_exit(void)
528 {
529         /* deregister this driver from the USB subsystem */
530         usb_deregister(&b2c2_usb_driver);
531 }
532
533 module_init (b2c2_usb_init);
534 module_exit (b2c2_usb_exit);
535
536 MODULE_AUTHOR(DRIVER_AUTHOR);
537 MODULE_DESCRIPTION(DRIVER_DESC);
538 MODULE_LICENSE("GPL");